Android服务stopSelf(int)

时间:2014-01-12 22:29:17

标签: android android-service

这是我的代码 -

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将匹配,并根据该文档服务将死?所有其他早期的“开始”将被杀死?

如果答案是“是”,那么实现该服务的最佳做法是什么,直到所有早期开始都没有完成才会杀死该服务。

3 个答案:

答案 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/posaconcurrencyhttp://www.coursera.org/course/posacommunication中进行了描述。

道格

答案 2 :(得分:0)

解决方案是维护一个以起始ID为键的布尔哈希映射。然后在您的工作线程中,而不是调用stopSelf(int)调用执行以下操作的自定义方法:

使用起始ID作为键将哈希映射条目设置为true。按升序迭代键并调用stopSelf(key),直到遇到false条目。