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

在Android开发中,咱们一般会将一些耗时操做放到一个Service中执行,可是普通的Service默认是运行在主线程中的,咱们没法直接在主线程中执行耗时操做,这就须要咱们本身在Service中维护一个子线程,相对来讲比较麻烦。为了解决这个问题,Google为咱们提供了一个IntentService,与普通的Service相比,IntentService会自动建立一个子线程用来执行任务,而且当任务执行完成后,IntentService会自动关闭服务,使用起来很是方便。java

##IntentService的使用方法 IntentService的使用方法很是简单,举一个简单的例子:markdown

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便可:ide

Intent intent = new Intent(MainActivity.this,IntentServiceExample.class);
startService(intent);
复制代码

经过log日志能够看到,onHandleIntent方法是运行在一个子线程中的:oop

E/Test: IntentService[IntentServiceExample]:task start
E/Test: IntentService[IntentServiceExample]:task finish
复制代码

须要注意的是使用IntentService也须要在AndroidManifest文件中进行注册,不然IntentService将没法正常工做。学习

##HandlerThread工做原理解析ui

如今咱们已经掌握了IntentService的基本使用方法了,可是在分析IntentService的工做原理以前,咱们首先来看一个名为HandlerThread的类,由于HandlerThread是IntentService中很是重要的一个对象,所以了解HandlerThread的原理有助于咱们去学习IntentService的工做机制。this

从HandlerThread的名字咱们就能看出,HandlerThread应该是继承自Thread类,所以它自己也是一个Thread。其中run方法是HandlerThread中一个比较重要的方法,咱们来看一下run方法的源码:spa

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。

相关文章
相关标签/搜索