美文网首页
IntentService 示例与详解

IntentService 示例与详解

作者: jacky123 | 来源:发表于2016-07-09 15:49 被阅读488次

    为什么要用IntentService

    IntentService 与 Service 相比的好处:一方面不需要自己去 new Thread 了;另一方面不需要考虑在什么时候关闭该 Service 了。


    源码解析

    当IntentService第一次启动,它的onCreate方法会被调用,该方法会创建一个HandlerThread,然后使用它的Looper来构造一个Handler对象mServiceHandler,这样通过mServiceHandler发送的消息最终都会在HandlerThread中执行。

    @Override
    public void onCreate() {
        // TODO: It would be nice to have an option to hold a partial wakelock
        // during processing, and to have a static startService(Context, Intent)
        // method that would launch the service & hand off a wakelock.
    
        super.onCreate();
        /**
         * HandlerThread ,Handy class for starting a new thread that has a looper。
         * 因为HandlerThread是一个Thread,我们调用其start方法就会调用run方法,其中会通过 Looper.myLooper()获取当前线程的looper对象
         */
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();
    
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }
    
    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            /**
             * use the provided {@link Looper} instead of the default one.
             */
            super(looper);
        }
    
        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            /**
             * 自己停止Service服务
             */
            stopSelf(msg.arg1);
        }
    }
    

    每次启动IntentService,它的onStartCommand方法就会被调用一次,onStartCommand调用了onStart方法。

    @Override
    public void onStart(Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }
    

    IntentService仅仅通过mServiceHandler发送了一条消息,这个消息会在HandlerThread中处理。mServiceHandler收到消息后,会将Intent对象传递给onHandleIntent方法处理。

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            /**
             * use the provided {@link Looper} instead of the default one.
             */
            super(looper);
        }
    
        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            /**
             * 尝试自己停止Service服务
             */
            stopSelf(msg.arg1);
        }
    }
    

    当onHandleIntent方法执行结束之后,IntentService会尝试通过stopSelf(int startId)来尝试停止服务。之所以不用stopSelf()来停止服务,是因为stopSelf()会立刻停止服务,而stopSelf(int startId)则会等待所有的消息都处理完毕才回终止服务。一般来说,stopSelf(int startId)在尝试停止服务之前会判断最近启动服务的次数是否和startId相等,如果相等则立刻停止服务。

    2. 为什么不建议通过 bindService() 启动 IntentService?
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    

    IntentService 源码中的 onBind() 默认返回 null;不适合 bindService() 启动服务,如果你执意要 bindService() 来启动 IntentService,可能因为你想通过 Binder 或 Messenger 使得 IntentService 和 Activity 可以通信,这样那么 onHandleIntent() 不会被回调,相当于在你使用 Service 而不是 IntentService。

    3. 为什么多次启动 IntentService 会顺序执行事件,停止服务后,后续的事件得不到执行?

    IntentService 中使用的 Handler、Looper、MessageQueue 机制把消息发送到线程中去执行的,所以多次启动 IntentService 不会重新创建新的服务和新的线程,只是把消息加入消息队列中等待执行,而如果服务停止,会清除消息队列中的消息,后续的事件得不到执行。

    @Override
    public void onStart(Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }
    
    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }
    

    参考资料

    相关文章

      网友评论

          本文标题:IntentService 示例与详解

          本文链接:https://www.haomeiwen.com/subject/honrjttx.html