0

在我的 Android 应用程序中有一个服务执行长时间运行的任务(例如播放音乐),它可以处于以下两种状态之一:运行或暂停。有一个“暂停/恢复”图像按钮可以暂停/恢复任务。由于其他原因(不是来自 UI),任务也可能被暂停。根据任务的当前状态(运行或暂停),按钮的外观应有所不同。所以我需要将按钮图像与任务的实际状态同步。

现在我想出了以下解决方案:我的服务有静态pauseresume方法,它们向自己发送意图,如下所示:

public static void pause(Context context) {
    Intent intent = new Intent(context, MyService.class);
    intent.putExtra("PAUSE", true);
    context.startService(intent);
}

public static void resume(Context context) {
    Intent intent = new Intent(context, MyService.class);
    intent.putExtra("RESUME", true);
    context.startService(intent);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    if (intent.getBooleanExtra("PAUSE", false)) {
        doPause();
    } else if (intent.getBooleanExtra("RESUME", false)) {
        doResume();
    }
    return START_STICKY;
}

由于doPause()anddoResume()也可以从其他地方调用,所以我不能在调用MyService.pause()/时将图像设置为 ImageButton MyService.resume():按钮图像和任务的实际状态可能会变得不同步。相反,我使用 LocalBroadcastManager 在应该更新按钮时通知活动:

public void doPause() {
    paused = true;

    ... // Do some stuff to pause the service

    // Notify about state change
    Intent intent = new Intent("SERIVCE_STATE_CHANGED");
    intent.putExtra("PAUSED", true);
    LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}

代码doResume()类似。因此,我的活动注册了接收器并将图像设置为onReceive().

该解决方案似乎有效。但我的问题是是否有更好/更简单的方法来实现相同的目标?有什么最佳实践吗?

4

1 回答 1

1

我不认为你的解决方案是坏的。但是,可以说更好的另一种方法是使用 Android 数据绑定。

这样做的方式是,创建一个表示服务状态的模型对象。例如Player.isPlaying,代表服务状态。然后在服务中,您将设置 isPlaying 状态。

然后在您的布局中,您将使用数据绑定将该模型对象 isPlaying 状态链接到 UI,但是您想要设置它,例如:

android:background="@{player.isPlaying ? @drawable/pause : @drawable/play}"

我认为这可能是一个更好的解决方案的原因是,它直接将 UI 状态与服务 1:1 联系起来。从概念上讲,我认为广播可以来自多个来源。不过,我认为只有一个广播源没有问题,这就是为什么我不认为您当前的解决方案很糟糕。

您可以在此处查看有关 Google I/O 2016 数据绑定的详细视频:https ://www.youtube.com/watch?v=DAmmN7m3wLU

于 2016-09-12T14:04:36.700 回答