在我的Android应用程序中,有一个服务执行长时间运行的任务(例如播放音乐),该任务可以处于以下两种状态之一:运行或暂停。有一个“暂停/恢复”图像按钮可暂停/恢复任务。此外,由于其他原因(不是来自UI),任务可能会暂停。按钮的外观应根据任务的当前状态(运行或暂停)而有所不同。所以我需要将按钮图像与任务的实际状态同步。
现在我想出了以下解决方案:
我的服务具有静态pause
和resume
方法,可以像这样向自己发送意图:
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()
和doResume()
也可以从其他地方调用,因此我无法在调用MyService.pause()
/ MyService.resume()
时将图像设置为ImageButton:按钮图像并且任务的实际状态可能变得不同步。相反,当使用按钮时,我使用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()
。
解决方案似乎有效。但我的问题是,是否有更好/更简单的方法来实现同一目标?任何最佳做法?
答案 0 :(得分: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