IntentService的由来
众所周知service
默认是运行在主线程中的,如果我们需要在service
中进行耗时操作,往往我们的做法就是在service
的onStart
方法中开启一个子线程,然后将耗时操作放到子线程中,但是service
一旦开启,除非我们调用stopService
或者stopSelf
,服务才会停止,如何实现在service
中直接进行耗时操作?如何实现service
的即用即停呢?这是IntentService
就横空出世了。我们来看下官方介绍:
the service is started as needed, handles each Intent in turn using a workerthread, and stops itself when it runs out of work.
IntentService
会根据需求开启一个工作线程来处理这些需求,并且当所有的工作完成后关闭自身。
IntentService的使用
1public class MyIntentService extends IntentService {
2
3 private static final String TAG ="MyIntentService";
4
5 public MyIntentService() {
6 super("myIntentService");
7 }
8
9 public MyIntentService(String name) {
10 super(name);
11 }
12
13 @Override
14 public void onCreate() {
15 super.onCreate();
16 Log.i(TAG, "onCreate");
17 }
18
19 @Override
20 public void onStart(@Nullable Intent intent, int startId) {
21 super.onStart(intent, startId);
22 Log.i(TAG, "onStart");
23 }
24
25
26 @Override
27 public void onDestroy() {
28 super.onDestroy();
29 Log.i(TAG, "onDestroy");
30 }
31
32 @Override
33 protected void onHandleIntent(@Nullable Intent intent) {
34 Log.i(TAG, "onHandleIntent start");
35 try {
36 Thread.sleep(3000);
37 } catch (InterruptedException e) {
38
39 }
40 Log.i(TAG, "onHandleIntent end");
41 }
42}
43
44//开启服务
45startService(new Intent(MainActivity.this,MyIntentService.class));
下面是输出结果:
MyIntentService: onCreate
MyIntentService: onStart
MyIntentService: onHandleIntent start
MyIntentService: onHandleIntent end
MyIntentService: onDestroy
从Log
输出中我们可以看出当任务完成以后,service
调用onDestroy
,也验证上面我们所说的当IntentService
执行完任务后,会自动关闭。
IntentService源码解析
从IntentService
的使用中,我们可以看出其主要方法就是一个onHandleIntent
,而耗时操作也将在onHandleIntent
中执行。接下来我们看下onHandleIntent
的调用流程
1 private final class ServiceHandler extends Handler {
2 public ServiceHandler(Looper looper) {
3 super(looper);
4 }
5
6 @Override
7 public void handleMessage(Message msg) {
8 onHandleIntent((Intent)msg.obj);
9 stopSelf(msg.arg1);
10 }
11 }
可以看出来,IntentService
中保存了一个Handler
对象,而onHandleIntent
方法的调用是在Handler
的消息处理中,有处理消息的过程,必然也存在消息发送的过程,我们接下来看看消息发送的流程:
1 @Override
2 public void onCreate() {
3 super.onCreate();
4 HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
5 thread.start();
6 mServiceLooper = thread.getLooper();
7 mServiceHandler = new ServiceHandler(mServiceLooper);
8 }
9
10 @Override
11 public void onStart(Intent intent, int startId) {
12 Message msg = mServiceHandler.obtainMessage();
13 msg.arg1 = startId;
14 msg.obj = intent;
15 mServiceHandler.sendMessage(msg);
16 }
整个流程就很明确了,在Service
的onStart
方法中将传进来的intent
作为消息的obj创建消息并发送。而在Service
的onCreate
方法中创建了一个HandlerThread
,并从中取出一个Looper
对象作为Handler
的参数创建了一个Handler
对象,并使用这个Handler
对象发送消息和处理消息。而这其中有一个陌生的类就是HandlerThread
,我们来大胆预测下HandlerThread
的源码实现。onHandleIntent
中执行耗时操作,而onHandlerIntent
又是在Handler
的handleMessage
中调用,说明handler
消息处理过程在子线程中执行,而handler
消息处理又是在looper
的loop
方法中被调用,说明创建handler
对象传入的looper
对象在子线程中创建,并调用了loop
方法,我们来看下HandlerThread
的源码看下是否和我们预想的是否一致?
1 @Override
2 public void run() {
3 mTid = Process.myTid();
4 Looper.prepare();
5 synchronized (this) {
6 mLooper = Looper.myLooper();
7 notifyAll();
8 }
9 Process.setThreadPriority(mPriority);
10 onLooperPrepared();
11 Looper.loop();
12 mTid = -1;
13 }
可以看出和我们预想的一样的,在thread
的run
方法中调用Looper.prepare
方法创建与当前子线程相关的Looper
对象,并调用Looper.loop
方法获取消息队列里面的消息。
好了,我们来梳理一下IntentService整个流程
- 在
IntentService
的onCreate
方法中创建一个HandlerThread
线程并启动,HandlerThread
的run
方法中创建一个Looper
对象并开始loop
消息,并将Looper
对象作为参数创建Handler
。 - 在
IntentService
的onStart
方法中将传入的Intent
作为Message
的obj
,并使用Handler
发送。 Handler
接收到消息以后,调用handleMessage
方法,将耗时操作转移到HandlerThread
线程中。