前言
IntentService
本质上也属于 Service
,它可以说是一个使用起来更为简单的 Service
。在我们基本的 Service
使用过程中,我们需要在 Service
中自己开启子线程进行耗时操作,并且在 Service
执行结束后还要调用 stopSelf
或 stopService
方法来关闭 Service
,而使用 IntentService
的话,这些问题将通通不需要关注。因为 IntentService
内部就是默认执行在子线程中的,并且在执行结束后它会帮我们自动停止 Service
。
在学习本章知识的时候,你需要先知晓以下知识点:
- Service的基本使用
- Android的异步消息处理机制
如果你对这两块知识点还不够熟悉的话,可以点击上面的超链接进行学习,那么接下来就让我们开始 IntentService
的学习吧,首先我们学习一下它的使用。
IntentService 的使用
IntentService
的使用和 Service
非常的相似,也比 Service
更加简单,我们接下来创建一个 MyIntentService
类,并继承自 IntentService
。它的代码如下:
public class MyIntentService extends IntentService {
private static final String TAG = MyIntentService.class.getSimpleName();public MyIntentService() {
super("MyIntentService");}@Overridepublic void onCreate() {
super.onCreate();Log.d(TAG,"onCreate");}@Overrideprotected void onHandleIntent(@Nullable Intent intent) {
Log.d(TAG, "onHandleIntent's thread: " + Thread.currentThread());}@Overridepublic void onDestroy() {
super.onDestroy();Log.d(TAG, "onDestroy");}}
我们对里面的 3 个生命周期中的方法进行重写,它们分别是 onCreate
、onHandleIntent
和 onDestroy
。如果你之前学习过 Service
的话,对 onCreate
和 onDestroy
应当是相当熟悉的了,它们就是分别对应于 IntentService
启动时和停止时的方法。而 onHandleIntent
则比较陌生了,其实这个方法就是我们在 IntentService
中执行主要逻辑的方法,它默认是运行在子线程中的。这里我们对这 3 个方法只是简单地打印 Log
,特别的我们会打印出 onHandleIntent
的线程,验证它是否真的运行在子线程中。
接下来我们就为 MainActivity
中添加一个按钮,通过按钮来调用 startService
方法来启动我们的 IntentService
,代码如下:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private Button startServiceBtn;@Overrideprotected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);Log.d("MainActivity", Thread.currentThread().getName());setContentView(R.layout.activity_main);startServiceBtn = (Button)findViewById(R.id.start_service);startServiceBtn.setOnClickListener(this);}@Overridepublic void onClick(View v) {
switch (v.getId()){
case R.id.start_service:Intent startIntent = new Intent(this, MyIntentService.class);startService(startIntent);break;}}
}
这段代码逻辑相当简单,这里就不再做过多赘述了,我们在 Activity
的 onCreate
方法中也通过 Log
打印了线程的名字,运行程序,输出结果如下:
D/MainActivity: main
D/MyIntentService: onCreate
D/MyIntentService: onHandleIntent’s thread: Thread[IntentService[MyIntentService],5,main]
D/MyIntentService: onDestroy
可以看到,onHandleIntent
所处的线程与主线程名称不同,说明它确实是运行在子线程房中的。并且在运行完毕之后,运行了 onDestroy
方法,也证实 IntentService
在运行结束后确实会自动进行停止。
在通过例子验证了 IntentService
之后,我们接下来从源码的层面分析它是如何实现这些特性的。
源码分析
由于 IntentService
的源码量不算多,只有一百来行,所以这里我就直接将它都贴了过来逐步分析。它的源码如下:
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;private volatile ServiceHandler mServiceHandler;......@WorkerThreadprotected abstract void onHandleIntent(@Nullable Intent intent);
}
首先我们知道了这是一个继承自 Service
的抽象类,而它的抽象方法其实只有一个,就是 onHandleIntent
方法,它是我们实现具体逻辑的地方,就是需要我们自己去重写的。
接着我们看到它的成员 mServiceLooper
和 mServiceHandler
,它们分别是 Looper
类型和 ServiceHandler
类型的对象,而 ServiceHandler
又是继承自 Handler
的,看到这里我们应该非常熟悉了,它就是利用 Android 的异步消息处理机制来切换我们的线程的。
我们来看看 ServiceHandler
的实现代码:
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);}@Overridepublic void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);stopSelf(msg.arg1);}
}
可以看到它的构造方法就是将一个 Looper
对象传给父类的构造方法进行 Handler
的初始化。
接着看到 handleMessage
方法,在这里会调用 onHandleIntent
方法,它就是在我们的自定义 IntentService
中被实现的嘛,然后在它执行完之后会调用 stopSelf
方法停止 Service
,这也就是我们之前所说的 IntentService
在执行完之后会自动停止的原因了。那么我们只要找到了通过 mServiceHandler
发送消息的地方,我们就找到了关键的地方了。
接下来我们继续看到 onCreate
方法,它的代码如下:
@Override
public void onCreate() {
super.onCreate();HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");thread.start();mServiceLooper = thread.getLooper();mServiceHandler = new ServiceHandler(mServiceLooper);
}
我们看到第 3 行,这里创建了一个 HandlerThread
对象 thread
,我们来看看这个类的实现是什么样子的:
public class HandlerThread extends Thread {
int mPriority;int mTid = -1;Looper mLooper;private @Nullable Handler mHandler;public HandlerThread(String name) {
super(name);mPriority = Process.THREAD_PRIORITY_DEFAULT;}......
}
可以看到,它是继承自 Thread
的一个类,它内部同样也维护了两个重要的成员 mLooper
和 mHandler
。我们直接看到它的 run
方法:
@Override
public void run() {
mTid = Process.myTid();Looper.prepare();synchronized (this) {
mLooper = Looper.myLooper();notifyAll();}Process.setThreadPriority(mPriority);onLooperPrepared();Looper.loop();mTid = -1;
}
可以看到 run
方法中所做的工作其实就是通过 Looper.prepare
方法创建一个 Looper
对象,然后在同步块中通过 Looper.myLooper
赋值给 mLooper
,紧接着在最后调用 Looper.loop
方法进入一个循环。
我们接着看到 getLooper
方法的实现:
public Looper getLooper() {
if (!isAlive()) {
return null;}// If the thread has been started, wait until the looper has been created.synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();} catch (InterruptedException e) {
}}}return mLooper;
}
这个方法做的工作也很简单,首先判断该线程是否还存活,不存活的话直接返回 null
,如果还存活的话,会在下面的同步块中判断 mLooper
对象是否已经创建,如果还未创建并且线程此时还存活的话,就会调用 wait
方法进入等待状态知道 mLooper
对象被创建为止,然后返回 mLooper
。
这里特别提到一点:既然有 wait
方法,那么肯定就要有 notify
或 notifyAll
方法。我们可以发现整个 HandlerThread
中只有在 run
方法中有一个 notifyAll
方法,它位于 mLooper = Looper.myLooper();
这句代码之后。这么做的原因是我们的 Handler
一般是在 UI 线程中创建的(IntentService
同样也是这么做的),也就是说,我们必须等到 mLooper
创建完成,才能正确的返回 getLooper
。wait
、notifyAll
就是为了解决这两个线程的同步问题。
最后我们看到 HandlerThread
的 quit
方法:
public boolean quit() {
Looper looper = getLooper();if (looper != null) {
looper.quit();return true;}return false;
}
这个方法首先通过 getLooper
获取到 mLooper
,如果不为空的话,就会执行 Looper
的 quit
方法来终止 Looper
,从而停止依赖于该 Looper
的 Handler
的工作。
在分析完 HandlerThread
的代码之后,我们继续回到 IntentService
的 onCreate
方法,为了方便观看这里我们就直接把它贴了过来:
@Override
public void onCreate() {
super.onCreate();HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");thread.start();mServiceLooper = thread.getLooper();mServiceHandler = new ServiceHandler(mServiceLooper);
}
首先构造出一个 HandlerThread
对象,然后通过 start
方法开启了这个子线程,执行它的 run
方法,它的 run
方法我们前面分析过,会在这个子线程中创建一个 Looper
对象然后赋值给 HandlerThread
的成员 mLooper
。紧接着 mServiceLooper
通过 HandlerThread
的 getLooper
方法赋值,getLooper
其实就是返回 HandlerThread
的 mLooper
成员。最后 mServiceHandler
将 mServiceLooper
作为参数传进它的构造方法中进行初始化,完成了对 mServiceHandler
的创建。
从 onCreate
这里我们也可以得出一个结论:mServiceHandler
的 handleMessage
方法是在子线程中执行的,因为它依赖的 Looper
就是位于子线程中的嘛。
接下来我们看到 IntentService
的 onStartCommand
方法,我们在前面的例子中说到过启动 IntentService
调用的就是 startService
方法,所以 onStartCommand
方法就会在 onCreate
方法后得到调用,它的实现如下:
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
可以看到,它调用了 onStart
方法,并将 intent
和 startId
作为参数传了进去,我们接下来看看 onStart
方法做了什么:
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();msg.arg1 = startId;msg.obj = intent;mServiceHandler.sendMessage(msg);
}
可以很清楚地看到 onStart
方法做的就是通过调用 mServiceHandler
的 sendMessage
方法发送消息了,然后就会调用 ServiceHandler
类中的 handleMessage
方法进行处理,在前面的分析中我们已经知道了 handleMessage
方法就是在子线程中调用 onHandleIntent
方法,这个方法是留待我们自己实现的,然后在执行完 onHandleIntent
方法之后就会调用 stopSelf
方法停止 Service
,这个方法最终调用的也是 onDestroy
方法,我们看到 onDestroy
方法的实现:
@Override
public void onDestroy() {
mServiceLooper.quit();
}
可以看到它就是调用 Looper
的 quit
方法退出,然后使 mServiceHandler
的工作终止。
到这里,我们对 IntentService
的源码解析就结束了,我们对它进行一下总结:
IntentService
是继承自Service
的一个类,它在内部维护了一个Looper
类型的成员mServiceLooper
和ServiceHandler
类型的成员mServiceHandler
,用于进行线程的切换。IntentService
通过startService
方法启动,所以它的生命周期应当是onCreate - onStartCommand - onDestroy
。- 在
onCreate
中进行了对mServiceLooper
和mServiceHandler
的初始化,要注意到mServiceLooper
是在子线程中运行的。 - 在
onStartCommand
中调用了onStart
方法,该方法通过mServiceHandler
发送消息给ServiceHandler
的handleMessage
方法进行处理。 ServiceHandler
的handleMessage
方法调用了onHandleIntent
方法和stopSelf
方法,onHandleIntent
方法就是我们需要自己实现的方法,stopSelf
方法最终会调用到onDestroy
方法,要注意到由于mServiceLooper
是在子线程中运行的,所以handleMessage
方法也是运行在子线程中的,同时它也实现了在IntentService
运行完后自动停止Service
。- 在
onDestroy
中调用Looper
的quit
方法退出mServiceLooper
,从而停止mServiceHandler
的运行。
最后我们通过图形的形式来从另一个角度总结 IntentService
:
到这里,我们 IntentService
相关的知识点就介绍完了,IntentService
的源码还是比较少的,只要对基本的 Service
以及 Android 的异步消息处理机制够熟悉,理解它的实现还是比较容易的,希望大家能够通过这篇文章有所收获,有问题的话可以在下方评论区给我留言。