Android SDK里面很多类名都起的让人傻傻分不清楚,本篇文章就是从IntentService这个组件的生命周期出发,深度剖析ThreadLocal、HandlerThread以及IntentService之间错综复杂的关系。
首先了解概念
ThreadLocal:线程的本地变量。该变量不与其他线程共享,只能在本线程内操作。
HandlerThread:一种经过包装的Thread。随着该thread启动,其内部的Looper会自动开始循环。
IntentService:一种经过包装的Service。该Service内部会自动开启一个线程用来执行任务,并在任务结束后自动结束。
敲黑板!记住结论:
- HandlerThread本质上仍是一个Thread。
- IntentService本质上仍是一个Service。
IntentService的生命周期
既然IntentService也是个Service,那么就从它的onCreate方法看起。
关注三个点:
- 实例化了一个HandlerThread,并启动该线程。
- 获取该HandlerThread中自带的Looper对象。
- 将获取到的Looper对象作为参数用来实例化ServiceHandler。
首先,通过阅读HandlerThread的源码,可以发现HandlerThread在run方法中会帮我们创建好一个Looper并让该Looper执行loop方法。在深入理解Handler、Looper与MessageQueue之间的关系一文中,我们详细的描述了Handler、Looper以及MesageQueue三者之间的关系。Looper循环是Handler能在线程中运行的前提条件。
所以我们可以理解为,IntentService的onCreate方法中所用到的HandlerThread,相当于是为IntentService快速的构建并启动了一个带有Looper的工作线程。
最后一点,就是ServiceHandler。
ServiceHandler的构造函数没什么好讲的,和普通Handler一样。重点在于其handleMessage方法。
handlerMessage方法用来处理由Looper循环MessageQueue所得到的Message。此处的代码逻辑为,当有Message发送来,则会调用onHandleIntent方法进行处理,而这个onHandleIntent方法则正是我们使用IntentService时必须要实现的抽象方法。当onHandleIntent方法执行完,便会调用Service的stopSelf方法终止该IntentService,以此达到任务执行完自动结束的效果。
下面放上IntentService的完整代码:
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
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);
}
}
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public IntentService(String name) {
super();
mName = name;
}
/**
* Sets intent redelivery preferences. Usually called from the constructor
* with your preferred semantics.
*
* <p>If enabled is true,
* {@link #onStartCommand(Intent, int, int)} will return
* {@link Service#START_REDELIVER_INTENT}, so if this process dies before
* {@link #onHandleIntent(Intent)} returns, the process will be restarted
* and the intent redelivered. If multiple Intents have been sent, only
* the most recent one is guaranteed to be redelivered.
*
* <p>If enabled is false (the default),
* {@link #onStartCommand(Intent, int, int)} will return
* {@link Service#START_NOT_STICKY}, and if the process dies, the Intent
* dies along with it.
*/
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@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;
}
@Override
public void onDestroy() {
mServiceLooper.quit();
}
/**
* Unless you provide binding for your service, you don't need to implement this
* method, because the default implementation returns null.
* @see android.app.Service#onBind
*/
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
/**
* This method is invoked on the worker thread with a request to process.
* Only one Intent is processed at a time, but the processing happens on a
* worker thread that runs independently from other application logic.
* So, if this code takes a long time, it will hold up other requests to
* the same IntentService, but it will not hold up anything else.
* When all requests have been handled, the IntentService stops itself,
* so you should not call {@link #stopSelf}.
*
* @param intent The value passed to {@link
* android.content.Context#startService(Intent)}.
* This may be null if the service is being restarted after
* its process has gone away; see
* {@link android.app.Service#onStartCommand}
* for details.
*/
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
最后结合代码完整的梳理一遍IntentService的执行过程:
①首先IntentService执行onCreate方法,该方法中会创建一个HandlerThread线程并实例化一个内部类ServiceHandler。
②随后,onStartCommand方法会调用onStart方法,在onStart方法内部,会构造一个Message,然后用ServiceHandler来发送该Message。
③再之后,ServiceHandler的handleMessage方法会对发来的Mesage进行处理,具体的处理逻辑则是交给抽象方法onHandleIntent来完成,而这个方法正是使用者使用IntentService必须要实现的方法,使用者应该将该Service要执行的任务写在该抽象方法的实现中。
④在onHandleIntent方法完成后,便会执行Service的stopSelf(int id)方法,来结束该IntentService。
⑤最后,在IntentService的onDestroy方法里,通过执行mServiceLooper的quit()方法,终止掉该Looper循环,也顺带结束了该IntentService对应的工作线程。
通过整体流程分析,我们可以发现,IntentService为我们封装好了工作线程的初始化、启动以及结束相关的代码,使得开发者能专注于业务逻辑的编写,减少了忘记结束Service所带来的内存泄漏的威胁。