最近看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相关的几个类都差很远,但是给我们提供的编码思路却是很有用的。