IntentService源码分析
首先还是介绍一下,IntentService是Service的子类,具有两个特点:**1.自动开启子线程执行任务;2.执行完成自动结束。**此外,一个IntentService可以start()多次,每次开启一个工作线程来执行,所有线程都停止后才可能调用onDestory()。
1.如何构成
首先来看InteneService的成员变量,只有四个,非常简单。
private volatile Looper mServiceLooper; // 用于保存工作线程的Looper以创建Handler
private volatile ServiceHandler mServiceHandler; // Intent的最终消费者
private String mName; // 服务名称
private boolean mRedelivery; // 是否可重复发送
其中,ServiceHandler是IntentService的内部类,继承自Handler。在其handleMessage()方法中调用了protected abstract void onHandleIntent(@Nullable Intent intent)
然后调用Service的stopSelf()方法,使得服务可以自动结束。
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); // 停止服务
}
}
2.如何在子线程中执行
那么,IntentService又是如何做到独立线程执行任务的呢?看看其onCreate()
方法便知。
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
HandlerThread是Android中定义的一个小工具类,可以说就是为Handler而生的Thread,看官方注解就能明白:Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called.
而在上面的onCreate()方法中也确实是这么使用的,先创建一个HandlerThread然后获取其Looper对象,并用之创建Handler。我们都知道,Handler的handleMessage()方法是执行在它所绑定的Looper所在线程中的,因此上面代码中mServiceHandler处理消息也是在子线程thread中了。
最后看看HandlerThread类的主要代码,确实非常handy哈哈。由于在run()方法中执行了Loop.prepare(),所以要求先start()也就可以理解了。
public class HandlerThread extends Thread {
Looper mLooper; // 线程中的Looper
private @Nullable Handler mHandler; // 可以直接由HandlerThread创建对应的Handler并返回
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) { // 同步块,保证同一IntentService多次start()顺序执行
mLooper = Looper.myLooper(); //
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop(); //
mTid = -1;
}
}
3.消息如何传递
然后来看下一个Intent如何封装在Message中进行传递。我们在使用IntentService时大概会先实现一个子类,覆盖onHandleIntent()
方法取出Bundle进行处理,然后使用如下代码启动任务。
Intent it=new Intent(getActivity(), MyIntentService.class);
Bundle bd=new Bundle();
bd.putString("xxx",yyy);
it.putExtras(bd);
startService(it);
那么就来看看IntentService的onStart()方法。
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId; // 启动标识,用于stopSelf()的识别
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
// Handler类
public final Message obtainMessage()
{
return Message.obtain(this);
}
第一句实际上调用了父类Handler的方法,从Message缓存池中复用一个Message对象。然后将Intent对象保存在其obj中,最后调用Handler的sendMessage()方法。
再简单提一下Handler消息机制的内容,该方法最终会调用mServiceLooper(从thread获取的Looper对象)中的MessageQueue中enqueueMessage()
方法将msg加入到thread的消息队列中,而thread启动后其Looper.loop()循环就已开始,拿出消息队列中的msg对象进入处理阶段,也就是著名的msg.target.dispatchMessage(msg)
了,这个target就是mServiceHandler,而dispatch~方法则会执行到handleMessage(),从msg中取出Intent并传给我们自己的处理逻辑,等待期执行完成,stopSelf()。
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}