这是我的代码 -
public class BackgroundService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
new ServiceThread(startId);
return START_NOT_STICKY;
}
class ServiceThread extends Thread {
private int startId;
ServiceThread(int startId) {
this.startId = startId;
}
@Override
public void run() {
super.run();
try {
Thread.sleep((long) Math.random());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
stopSelf(startId);
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
根据此链接“Stopping a service”,我可以/应该使用收到的“startId”调用stopSelf。
但是,如果您的服务处理对onStartCommand()的多个请求 同时,你不应该在完成后停止服务 处理一个开始请求,因为你可能已经收到了一个 新的启动请求(在第一个请求结束时停止) 终止第二个)。要避免此问题,您可以使用 stopSelf(int)确保您停止服务的请求 始终基于最近的启动请求。也就是说,当你打电话 stopSelf(int),你传递开始请求的ID(startId 传递给停止请求所对应的onStartCommand())。 然后,如果服务在您能够之前收到新的启动请求 要调用stopSelf(int),那么ID将不匹配,服务将匹配 不要停止。
我的问题是,如果我用最后一个“startId”调用stopSelf,会发生什么,仍然有些早期的开始仍未完成。在这种情况下,startId将匹配,并根据该文档服务将死?所有其他早期的“开始”将被杀死?
如果答案是“是”,那么实现该服务的最佳做法是什么,直到所有早期开始都没有完成才会杀死该服务。
答案 0 :(得分:3)
我昨天遇到了完全相同的问题。我想我在Service.stopSelfResult(int startId)方法的javadoc中找到了答案。
如果您最终可能无序处理ID(例如通过在不同的线程上调度它们),那么您有责任按照收到它们的顺序停止它们。
答案 1 :(得分:1)
这是一个微妙的问题 - 我不确定上述任何解决方案是否足够/有效。我使用的解决方案基于一个名为ThreadPoolService
的类,它扩展Service
并按如下方式运行:
HashSet<Integer>
,用于存储startId
onStartCommand()
int
的{{1}}字段,用于存储mLastStartId
传递的最新startId
onStartCommand()
或ExecutorService
newCachedThreadPool()
newFixedThreadPool()
方法,该方法将beginIntentProcessing()
参数添加到startId
并在HashSet
startId
mLastStartId
方法,该方法从endIntentProcessing()
中删除startId
参数,并在HashSet
非空时返回。但是,如果HashSet
为空,则会调用HashSet
超类上的stopSelf()
方法,并传入Service
。我省略了解决方案的一些细节,但它有效并解决了上述潜在问题。我将在即将发布的Android并发编程MOOC中介绍这个主题(以及许多其他内容),这些内容在http://www.coursera.org/course/posaconcurrency和http://www.coursera.org/course/posacommunication中进行了描述。
道格
答案 2 :(得分:0)
解决方案是维护一个以起始ID为键的布尔哈希映射。然后在您的工作线程中,而不是调用stopSelf(int)
调用执行以下操作的自定义方法:
使用起始ID作为键将哈希映射条目设置为true
。按升序迭代键并调用stopSelf(key)
,直到遇到false
条目。