前言:IntentService在我们平常的开发过程中是非常常见的,我们都习惯于用它去处理一些耗时任务,但是对于它的内部机制,你真的了解?下面我们通过几个常见的面试题,来对IntentService一一剖析。想要了解更多关于Android多线程知识,请移步 Android多线程专栏。
常见面试问题:
面对如上面试题目,你能够一一对答如流?接下来我们就围绕这三个题目,对IntentService做一个全方位的剖析。
IntentService的作用、优势和工作机制:
IntentService的作用与优势:IntentService也是一种服务(Service)。其内部有一个特别的线程(HandlerThread),绑定一个Looper(维护一个消息队列),支持串形执行消息队列中的消息。同时,IntentService(服务)比普通的线程优先级更高,特别适用于处理高优先级的任务。最后,因为它有较高的优先级,因此服务不容易被杀死,可靠性较强。
IntentService工作机制:
第一步:自定义Intentservice服务:
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
//onCreate方法在主线程中执行
@Override
public void onCreate() {
super.onCreate();
}
//onStart方法在主线程中执行
@Override
public void onStart(@Nullable Intent intent, int startId) {
super.onStart(intent, startId);
}
//onHandleIntent方法在子线程中执行,用于串形处理耗时任务
@Override
protected void onHandleIntent(@Nullable Intent intent) {
//处理耗时任务,通过测试可以发现,当有多个任务需要处理时,取出一个任务执行时,该方法会阻塞,直到这个任务处理完毕,才会取出下一个任务执行
}
//onDestroy方法在主线程中执行
@Override
public void onDestroy() {
super.onDestroy();
}
}
第二步:开始服务
//通过下面的方式去启动服务
private void startService() {
Intent intent = new Intent(MainActivity.this, MyIntentService.class);
startService(intent);
}
第三步:当我们启动服务后,会先回调用IntentService中的onCreate方法,进行一些初始化工作:
@Override
public void onCreate() {
super.onCreate();
//这就是处理耗时任务的工作线程,这里初始化并启动工作线程,用于处理任务
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
//初始化ServiceHandler,并且与工作线程的Looper绑定在一起
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
看到这里,可能大家还是一脸懵逼。HandlerThread是个什么东东,ServiceHandler又是个什么鬼,在这里有什么用处??带着这些疑问,我们接着往下看:
//这就是HandlerThread的关键代码
public class HandlerThread extends Thread {
//线程优先级
int mPriority;
int mTid = -1;
//Looper对象,用于维护和轮询消息队列
Looper mLooper;
//Handler对象,用于发送和处理消息
private @Nullable Handler mHandler;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
protected void onLooperPrepared() {
}
//线程执行的关键代码,当启动线程后,就会进入下面的逻辑处理
@Override
public void run() {
mTid = Process.myTid();
//给当前线程创建Looper对象
Looper.prepare();
//同步获取Looper
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
//设置优先级
Process.setThreadPriority(mPriority);
//可以看到上面方法的定义,是空方法实现
onLooperPrepared();
//开启消息轮询,在前面讲过,loop方法最终会调用Handler的HandleMessage方法去处理轮询到的消息
Looper.loop();
mTid = -1;
}
}
上面对HandlerThread类的分析已经很清晰了,当回调IntentService的onCreate方法的时候,创建一个HandlerThread对象,并且启动这个线程。一旦线程开始工作,就会维护一个消息队列,并且进入无限的消息轮询处理过程。可能有同学对上面讲到的Looper工作机制还是一头雾水,不用着急,请移步 Handler消息机制详解 查看Looper工作详情。想要了解更多关于Android多线程知识,请移步 Android多线程专栏。
//这就是ServiceHandler类的完整定义
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
//在接收到消息的时候,调用onHandleIntent方法对消息进行处理,处理完所有消息后,停止服务
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
看到这里,IntentService的onCreate方法逻辑就很清晰了。当Looper轮询到有新的消息时,就会通过Handler将消息发送出去,接下来Handler就会调用handleMessage方法处理消息。最终,handleMessage方法还是会调用我们自己实现的onHandleIntent方法去处理耗时任务。
第四步:在处理完onCreate方法后,立即进入IntentService的onStart方法,看一下onStart的内部逻辑:
//在这里我们才会收到开始服务时的Intent对象,并且创建一个新的Message对象,通过mServiceHandler发送出去
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
通过onStart方法可以看出,在这里我们才会拿到Intent对象,并创建Message对象通过mServiceHandler发送出去。因此,这时我们的消息队列才能轮询到新的消息,并且对消息进行处理。前面说到,当Looper轮询到新的消息后,就会调用handler的handleMessage方法去处理消息,handleMessage方法又会调用onHandleIntent方法。
第五步:调用onHandleIntent方法
//工作在工作线程的抽象方法,因此我们定义IntengService时必须重写这个方法,用于处理耗时任务
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
第六步:当处理完所有的任务后,IntentService会调用stopself方法停止服务,并且回调onDestroy方法
@Override
public void onDestroy() {
//调用Looper的quit方法,内部其实是调用MessageQueue的quit方法,移除消息并停止消息的轮询
mServiceLooper.quit();
}
以上就是从创建IntentService服务到服务销毁的完整生命周期,回顾一下完整的调用链:
//自定义IntentService,,并且重写onHandleIntent方法
public class MyIntentService extends IntentService{}
//开始服务
Intent intent = new Intent(MainActivity.this, MyIntentService.class);
startService(intent);
//回调onCreate方法(创建HandlerThread和ServiceHandler对象,绑定)
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
//回调onStart方法,发送消息
mServiceHandler.sendMessage(msg);
//HandlerThread中Looper轮询到消息队列有新消息,调用Handler的handleMessage方法处理消息
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);}
//调用我们重写的onHandleIntent方法处理耗时任务
protected abstract void onHandleIntent(@Nullable Intent intent);
//调用onDestory方法退出消息队列
mServiceLooper.quit();
通过IntentService实现任务并行处理
前面说过,多任务到来时,都是首先通过onHandleIntent方法去处理的。因此,要实现多任务并行处理的话,可以在这个方法中实现线程池处理任务,当有任务到来时,不阻塞当前线程,直接交给线程池去处理。这样,相当于HandlerThread仅用于任务的管理与分配,并不参与执行,而真正处理耗时任务的是线程池。
如果有同学有更好的实现方式,欢迎提出来,大家共同学习。ps
:对线程池有不清楚的同学,可以移步:Android多线程之线程池Executor详解。
总结:IntentService在我们我们的开发中应用是很广泛的,希望通过我的分享,能够使大家对它有更深的理解,并且学以致用。