美文网首页面试储备资料Android开发程序员
Android IntentService的使用与工作原理解析

Android IntentService的使用与工作原理解析

作者: RainMi | 来源:发表于2018-04-19 14:13 被阅读50次

    在Android开发中,我们通常会将一些耗时操作放到一个Service中执行,但是普通的Service默认是运行在主线程中的,我们无法直接在主线程中执行耗时操作,这就需要我们自己在Service中维护一个子线程,相对来说比较麻烦。为了解决这个问题,Google为我们提供了一个IntentService,与普通的Service相比,IntentService会自动创建一个子线程用来执行任务,并且当任务执行完成后,IntentService会自动关闭服务,使用起来非常方便。

    IntentService的使用方法

    IntentService的使用方法非常简单,举一个简单的例子:

    public class IntentServiceExample extends IntentService {
    
        /**
         * 在构造方法中调用了父类的构造方法IntentService(String name)
         * 参数name用来对工作线程进行命名,方便进行调试
         */
        public IntentServiceExample() {
            super("IntentServiceExample");
        }
    
        /**
         * 重写父类的onHandleIntent方法,在该方法中实现自己所需的业务逻辑
         */
        @Override
        protected void onHandleIntent(@Nullable Intent intent) {
            try {
                Log.e("Test", Thread.currentThread().getName() + ":task start");
                Thread.sleep(3000);//让线程休眠3秒,用来模拟耗时任务
                Log.e("Test", Thread.currentThread().getName() + ":task finish");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    

    我们首先要新建一个类来继承自IntentService,然后重写onHandleIntent方法,并在该方法中实现我们所需的业务逻辑,然后我们只需要像启动一个普通Service那样来启动IntentService即可:

    Intent intent = new Intent(MainActivity.this,IntentServiceExample.class);
    startService(intent);
    

    通过log日志可以看到,onHandleIntent方法是运行在一个子线程中的:

    E/Test: IntentService[IntentServiceExample]:task start
    E/Test: IntentService[IntentServiceExample]:task finish
    

    需要注意的是使用IntentService也需要在AndroidManifest文件中进行注册,否则IntentService将无法正常工作。

    HandlerThread工作原理解析

    现在我们已经掌握了IntentService的基本使用方法了,但是在分析IntentService的工作原理之前,我们首先来看一个名为HandlerThread的类,因为HandlerThread是IntentService中非常重要的一个对象,因此了解HandlerThread的原理有助于我们去学习IntentService的工作机制。

    从HandlerThread的名字我们就能看出,HandlerThread应该是继承自Thread类,因此它本身也是一个Thread。其中run方法是HandlerThread中一个比较重要的方法,我们来看一下run方法的源码:

    public class HandlerThread extends Thread {
        Looper mLooper;
    
        @Override
        public void run() {
            mTid = Process.myTid();
            Looper.prepare();   //调用Looper的prepare方法
            synchronized (this) {
                mLooper = Looper.myLooper();
                notifyAll();
            }
            Process.setThreadPriority(mPriority);
            onLooperPrepared();
            Looper.loop();  //调用Looper的loop方法
            mTid = -1;
        }
        ...
    }
    

    可以看到,在HandlerThread的run方法中调用了Looper的prepare方法和loop方法。由此我们可以得知,HandlerThread与普通Thread的最大区别就在于,HandlerThread默认开启了该线程中的消息循环系统。(关于Android中的消息系统,不了解的同学可以去看一下我的另一篇博客Android中的消息系统————Handler,MessageQueue与Looper)

    HandlerThread还提供了一个getLooper方法,用来获取该线程所对应的Looper:

        public Looper getLooper() {
            if (!isAlive()) {
                return null;
            }
            
            // 如果该线程已经被启动,但是尚未开始消息循环,则等待直到消息循环系统启动完成
            synchronized (this) {
                while (isAlive() && mLooper == null) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                    }
                }
            }
            return mLooper;
        }
    

    这样我们便可以通过HandlerThread来很方便的来处理一些业务逻辑,IntentService便是一个运用了HandlerThread的典型例子,接下来我们便一起来分析一下IntentService的工作原理。

    IntentService的工作原理

    在了解了HandlerThread之后,我们终于可以来分析一下IntentService的工作原理了。先列出IntentService的源码:

    public abstract class IntentService extends Service {
        private volatile Looper mServiceLooper;
        private volatile ServiceHandler mServiceHandler;
    
        ...//省略部分代码
    
        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);
            }
        }
    
        @Override
        public void onCreate() {
            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);
        }
    
        @Override
        public void onDestroy() {
            mServiceLooper.quit();
        }
    
        @WorkerThread
        protected abstract void onHandleIntent(@Nullable Intent intent);
    }
    

    可以看到IntentService继承自Service,那么IntentService自然也拥有Service的所有生命周期方法。我们首先来看onCreate方法:

        @Override
        public void onCreate() {
            super.onCreate();
            HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
            thread.start();
            mServiceLooper = thread.getLooper();
            mServiceHandler = new ServiceHandler(mServiceLooper);
        }
    

    可以看到在onCreate方法中首先创建并开启了一个HandlerThread对象,前面我们已经分析过了HandlerThread的工作原理,可以得知这个HandlerThread线程会默认开启它的消息系统。之后又通过getLooper方法来获取了这个HandlerThread中的Looper对象,并通过这个Looper对象初始化了一个Handler,即mServiceHandler,因此通过mServiceHandler发送的message最终都会在这个HandlerThread线程中执行。(如果有同学对Android中的Handler与消息系统还不了解,建议先去看一下我的另一篇博客Android中的消息系统————Handler,MessageQueue与Looper)。

    然后我们再来看一下IntentService的onStart方法:

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

    onStart方法的代码很简单,就是通过之前在onCreate中初始化的mServiceHandler来发送了一条消息。我们来看一下mServiceHandler的代码:

        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);
            }
        }
    

    可以看到在ServiceHandler的handleMessage方法中直接调用了onHandleIntent方法,由于mServiceHandler是通过HandlerThread线程的Looper来创建的,因此onHandleIntent方法将在HandlerThread中被执行。

    在执行完onHandleIntent方法后,IntentService又调用了stopSelf方法来结束了本服务,因此IntentService是一种“用完即走”的服务,无需我们手动去结束服务。

    需要注意的是,IntentService的onBind方法默认返回为null,因此我们不建议使用bindService的方法来绑定IntentService:

        @Override
        @Nullable
        public IBinder onBind(Intent intent) {
            return null;
        }
    

    在Android8.0之后,谷歌加强了对后台服务的限制,当应用处于后台时,将无法通过startService开启后台服务,IntentService也受此限制的影响,Google推荐使用JobIntentService来替代IntentService。

    相关文章

      网友评论

        本文标题:Android IntentService的使用与工作原理解析

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