如何在服务中每次更改数据时更新 Activity

How to update Activity every time the data had been changed in Service

我正在编写我的第一个 Android 应用程序,它应该计算步数(通过加速度计,来自 http://www.gadgetsaint.com/android/create-pedometer-step-counter-android/ 的源代码)

那么我现在有什么:

  1. 具有三个 TextView 字段(步数、奖金、速度)的 MainActivity。
  2. 我检测步数并计算距离、奖励和 速度。

此服务是一个绑定服务,它由三个 类 组成:MyService、MyServiceBinder 和 MyServiceConnection。我已经按照 Xamarin.Android 文档和示例中的说明进行了操作:https://github.com/xamarin/monodroid-samples/tree/master/ApplicationFundamentals/ServiceSamples/BoundServiceDemo.

关键是每次我有一个步骤时,我都想在 MainActivity 上实时显示(更新那些文本视图)。而且我不明白如何以正确的方式做到这一点。事件?广播接收器?我被 binding/connection 弄得一团糟,这对我来说是一件新鲜事。 请帮助我让它工作!任何示例(Java 都可以)将非常有帮助。

这是源代码(我已经清除了多余的代码)。

MainActivity.cs

public class MainActivity : Activity
{
    //BOUND SERVICE: STEPSERVICE 
    MyServiceConnection myServiceConnection;

    //UI
    internal TextView textBonus, textSteps, textSpeed;

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.Main);

        textBonus = FindViewById<TextView>(Resource.Id.textViewBonus);
        textStep = FindViewById<TextView>(Resource.Id.textViewDistance);
        textSpeed = FindViewById<TextView>(Resource.Id.textViewSpeed);
    }

    protected override void OnStart()
    {
        base.OnStart();
        if (myServiceConnection == null)
        {
            myServiceConnection = new MyServiceConnection(this);
        }
        DoBindMyService();
    }

    private void DoBindMyService()
    {
        Intent serviceIntent = new Intent(this, typeof(MyService));
        BindService(serviceIntent, myServiceConnection, Bind.AutoCreate);
    }


    protected override void OnDestroy()
    {
        //stop services!
        base.OnDestroy();
    }

    private void UpdateUI()
    {
        RunOnUiThread(() =>
        {
            textBonus.Text = myServiceConnection.Binder.Service.Bonus;              
            textSteps.Text = myServiceConnection.Binder.Service.Steps;
            textSpeed.Text = myServiceConnection.Binder.Service.Speed;
        });
    }
}

MyService.cs

[Service]
public class MyService : Service, IStepListener, ISensorEventListener
{
    //counters
    private int bonus;
    public int Bonus
    {
        get { return bonus; }
        set { bonus = value; }
    }

    private int steps = 0;
    public int StepsT
    {
        get { return steps; }
        set
        {
            steps = value;
        }
    }

    private float speed = 0.0F;
    public float Speed
    {
        get { return speed; }
        set
        {
            speed = value;
        }
    }

    public IBinder Binder { get; private set; }

    public override IBinder OnBind(Intent intent)
    {
        this.Binder = new MyServiceBinder(this);
        return this.Binder;
    }

    public override void OnCreate()
    {
        base.OnCreate();
    }

    public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
    {
        return StartCommandResult.Sticky;
    }

    public void Step(long timeNs)
    {
        Steps++;
        Bonus++;
        Speed++;
    }

    public void OnAccuracyChanged(Sensor sensor, SensorStatus accuracy)
    {
        // We don't want to do anything here.
    }

    public void OnSensorChanged(SensorEvent e)
    {
        simpleStepDetector.UpdateAccel(e.Timestamp, e.Values[0], e.Values[1], e.Values[2]);
    }
}

MyServiceConnection.cs

public class MyServiceConnection : Java.Lang.Object, IServiceConnection
{
    MainActivity mainActivity;

    public MyServiceConnection(MainActivity activity)
    {
        IsConnected = false;
        Binder = null;
        mainActivity = activity;
    }

    public bool IsConnected { get; private set; }
    public MyServiceBinder Binder { get; private set; }

    public void OnServiceConnected(ComponentName name, IBinder service)
    {
        Binder = service as MyServiceBinder;
        IsConnected = this.Binder != null;

        string message = "onSecondServiceConnected - ";

        if (IsConnected)
        {
            message = message + " bound to service " + name.ClassName;
        }
        else
        {
            message = message + " not bound to service " + name.ClassName;
        }

        mainActivity.textSpeed.Text = message;
    }

    public void OnServiceDisconnected(ComponentName name)
    {
        IsConnected = false;
        Binder = null;
    }
}

MyServiceBinder.cs

public class MyServiceBinder : Binder
{
    public MyServiceBinder(MyService service)
    {
        this.Service = service;
    }

    public MyService Service { get; private set; }
}

PS。这是我的第一个问题。如有错误请见谅

可以通过三种方式完成。

  • 广播
  • 界面
  • 绑定服务

绑定服务

  • 在您的 MyServiceConnection 中添加:

    public MyService myService;
    

    并在您的 OnServiceConnected 方法中将其添加到 Binder = service as MyServiceBinder; 下:

    myService=Binder.Service;
    myService.SetActivity(mainActivity);
    
  • 在你的 MyService class 添加这个(这样你就可以在你的服务中获得 MainActivity 实例):

    MainActivity mainActivity;
    public void SetActivity(MainActivity activity) {
    this.mainActivity = activity;
    }
    

    并在您的 Step(long timeNs) 方法中添加 mainActivity.UpdateUI();,这样您就可以更新您的 UI。

  • 在您的 MainActivity 中将 private void UpdateUI() 替换为 public void UpdateUI()


界面

  • 添加IUpdate接口

    public interface IUpdate
    {
        void Update();
    }
    
  • 在您的 MyService 中添加:

    IUpdate update;
    public void SetIUpdate(IUpdate update) {
        this.update = update;
    }
    

    并在您的 Step(long timeNs) 方法中添加 this.update.Update();

  • 在你的MyServiceConnectionclass中实现IUpdate接口,所以它会像这样:

    public class MyServiceConnection : Java.Lang.Object, IServiceConnection,IUpdate
    {
         MainActivity mainAtivity;
    
        public MyServiceConnection(MainActivity activity)
    {
        IsConnected = false;
        Binder = null;
        mainActivity = activity;
    }
    
    public bool IsConnected { get; private set; }
    public MyServiceBinder Binder { get; private set; }
    public MyService myService;
    
    public void OnServiceConnected(ComponentName name, IBinder service)
    {
        Binder = service as MyServiceBinder;
        myService=Binder.Service;
        myService.SetIUpdate(this);
        //myService.SetActivity(mainActivity);
        IsConnected = this.Binder != null;
    
        string message = "onSecondServiceConnected - ";
    
        if (IsConnected)
        {
            message = message + " bound to service " + name.ClassName;
        }
        else
        {
            message = message + " not bound to service " + name.ClassName;
        }
    
        mainActivity.textSpeed.Text = message;
    }
    
    public void OnServiceDisconnected(ComponentName name)
    {
        IsConnected = false;
        Binder = null;
    }
    
    public void Update()
    {
        mainActivity.UpdateUI();
    }
    }
    

广播

这是你已经知道的。