美文网首页
android IntentService 源码分析

android IntentService 源码分析

作者: Yapple | 来源:发表于2021-05-23 16:31 被阅读0次

    上一篇文章讲了HandlerThread(https://www.jianshu.com/p/5522de58c320),这篇就讲讲使用到HandlerThread的IntentService。
    先简单介绍下IntentService,它继承自Service本身也是抽象类,因为Service本身是运行在主线程的,而在Service中开启子线程需要主动去调用stopService()/stopSelf()才能停止运行,容易遗忘或者逻辑漏洞导致Service无法及时关闭,出现内存泄露。IntentService就是用来解决这个问题的,本篇希望通过了分析其源码了解其实现这一功能的逻辑。

    使用:

    必须实现一个构造方法调用父类的含参构造器和 void onHandleIntent(@Nullable Intent intent) 方法

        public MyIntentService() {
            super("thread_name");
        }
    
        @Override
        protected void onHandleIntent(@Nullable Intent intent) {     
        }
    

    就是如此简单,构造方法的参数是开启子线程的名字,onHandleIntent会在子线程执行(可以打印该线程的名字,会发现和你传入构造器的参数是一样的)并且在执行完成后会关闭Service。

    实现逻辑

    IntentService算上注释一共也就181行,其实逻辑非常简单,简述一下就是这样的:
    1.在onCreate中创建工作线程(创建的对象就是上文所提到的HandlerThread),然后获取该线程绑定的Looper对象,并创建Handler绑定该Looper对象。
    2.在onStartCommand调用onStart,在onStart中创建Message对象并将intent意图打包到Message中通过Handler发送Message来保证在指定线程执行(也就是在onCreate创建的工作线程中执行)

    @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 thread = new HandlerThread("IntentService[" + mName + "]");
            thread.start();
    
            mServiceLooper = thread.getLooper();
            mServiceHandler = new ServiceHandler(mServiceLooper);
        }
    
        @Override
        public void onStart(@Nullable Intent intent, int startId) {
            Message msg = mServiceHandler.obtainMessage();
            msg.arg1 = startId;
            msg.obj = intent;
            mServiceHandler.sendMessage(msg);
        }
    
        /**
         * You should not override this method for your IntentService. Instead,
         * override {@link #onHandleIntent}, which the system calls when the IntentService
         * receives a start request.
         * @see android.app.Service#onStartCommand
         */
        @Override
        public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
            onStart(intent, startId);
            return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
        }
    

    这里有个重点就是Handler对象,如下,IntentService的内部类ServiceHandler实现了自己的handleMessage方法,这也就是其整个逻辑的关键所在:

    private final class ServiceHandler extends Handler {
            public ServiceHandler(Looper looper) {
                super(looper);
            }
    
            @Override
            public void handleMessage(Message msg) {
                onHandleIntent((Intent)msg.obj);
                stopSelf(msg.arg1);
            }
        }
    

    最终执行了onHandleIntent并将Intent传入,没毛病。
    然后,onHandleIntent执行完成之后调用stopSelf结束service,到这里“IntentService如何实现执行完任务后停止service的”这个问题就解决了。

    其它细节

    不过还有一点这里调用的stopSelf并不是我们日常使用的stopSelf(),它是带参数的:stopSelf(msg.arg)中的参数其实是startId,我们再onStart()方法中构建Message对象时会将它包装在Message中,他的作用其实就是保证我们所有的工作任务都完成了,才会真正的关闭service。
    也就是说我们可以重复的startService()执行多项后台任务,service会重复执行onStart()方法,每次发送不同的Message对象,这样子就可以像一个队列一样,确保每一项任务都完成之后再结束service,减少了多次创建service的消耗,可以说这个思路非常巧妙了。

    相关文章

      网友评论

          本文标题:android IntentService 源码分析

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