IntentService、HandlerThread相关

最近看Android基础,看过了Handler源码以及对应的HandlerThread,包括涉及到的ThreadLocal类,觉得很有意思。这几个类网上的源码分析比较多,也算是比较经典的Android源码,我就不分析了。这篇要记录的是另一个组件IntentService的源码相关,源码不多但是很有意思。

基本概念

IntentService应该属于那种用过的人很熟,没用过的人没听过的组件。源码的注释是这样的:

IntentService is a base class for {@link Service}s that handle asynchronous requests (expressed as {@link Intent}s) on demand. Clients send requests through {@link android.content.Context#startService(Intent)} calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.

简单的说,就是对于一般的Service来说,无论我们是start还是bind,都要自己管理Service的销毁。而IntentService呢,你可以把耗时操作扔给它,然后就不用管了,它自己处理完了以后就把自己关掉了。

源码分析

IntentService的源码太少了,我直接就把整个类copy了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

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

public IntentService(String name) {
super();
mName = name;
}

public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}

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

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

@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}

源码很少。首先这是一个抽象类,继承自Service,继承这个类的话必须实现onHandleIntent这个方法,也是在这个方法里我们进行耗时操作。

首先我们看onCreate方法,也是Service的生命周期毁掉方法,在这里首先会new一个HandlerThread出来,然后拿到这个HandlerThread线程对应的Looper,并使用这个Looper构建了一个ServiceHandler出来。ServiceHandler继承自Handler。在onStart方法里面,其实就是我们常用的用ServiceHandler发送了一个Message出去,在handleMessage方法这里会调用我们刚才说到的onHandleIntent方法,这个方法执行完毕以后接着调用stopSelf方法关掉自己。接着在onDestroy方法里会调用Looper.quit方法跳出Looper的循环。

逻辑很简单,我之所以觉得有意思的是Google的工程师真的是把自己写的组件用的淋漓尽致,看起来挺有用的IntentService,其实本质上就是利用了HandlerThread自己能够提供线程对应的Looper的特性,实现了一个IntentService-HandlerThread-Handler的绑定。用最简单易懂的代码实现了一个异步耗时任务的Service。

既然分析到这里,那么正好也分析一下HandlerThread的这个特性,源码仍然不多:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;

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.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}

public Looper getLooper() {
if (!isAlive()) {
return null;
}
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}

public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}

public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}

public int getThreadId() {
return mTid;
}
}

核心代码都在run方法里面了。其实就做了三件事情(假设看到这里的同学都熟悉Looper的源码了),Looper.prepare()mLooper = Looper.myLooper()Looper.loop()。熟悉Looper的同学肯定已经了解了,因为我们在任何地方想要自己实现一个子线程的Handler,都需要手动调用Looper.prepare()Looper.loop()。官方提供的这个HandlerThread其实就是帮我们做了这个事情,然后再对外暴露一个getLooper()方法,你就可以拿到这个线程对应的Looper来构建对应的Handler。IntentService也是利用了这一点,充分精简了代码。

总结

IntentService与其说是官方提供的一个组件,不如说是HandlerThread的一个最佳实践。他们的源码都没有什么深度,跟Handler相关的几个类都差很远,但是给我们提供的编码思路却是很有用的。