由于IntentService的源码涉及到了Handler、Looper、MessageQueue等知识点,所以如果你对Handler异步消息处理机制还不熟悉的话,建议先移步我的另一篇文章:https://www.jianshu.com/p/88aa46392f31。
相信大家都知道,Service默认是运行在主线程中的,如果我们需要在Service中处理耗时操作,这个时候就需要我们创建子线程去处理了,由于Service开启后是不会主动停止的,所以我们还需要在耗时操作处理完毕后手动去关闭当前Service。代码如下所示:
public class MyService extends Service{
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
new Thread(){
@Override
public void run() {
super.run();
//处理耗时操作
stopSelf();
}
}.start();
}
}
如果每次在Service中处理耗时操作都需要手动创建子线程并在耗时操作处理完毕后关闭当前Service的话,会不会感觉到有点麻烦?有没有一种简单的方式呢?Google考虑到了这种情况,为了方便我们操作,提供了IntentService,我们使用IntentService再来看下:
public class MyIntentService extends IntentService{
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
//直接处理耗时操作,无需手动停止service
}
}
有没有很简洁哈哈,不知道你有没有好奇为什么可以这样做呢?IntentService内部的原理是什么呢?下面让我们点进去它的源码来看下。
public abstract class IntentService extends Service {
我们可以看到IntentService是一个抽象类,继承自 Service,其实IntentService就是对Service做了一层封装。在IntentService中主要涉及到两个类:ServiceHandler 和 HandlerThread,我们会在后面详细讲解的。
既然IntentService继承自Service,那么我们调用StartService方法启动IntentService的时候肯定会走到它的onCreate方法,我们一起去看下:
@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);
}
我们可以看到,在onCreate方法中第二行创建了一个HandlerThread实例对象并调用了它的start()方法。其实HandlerThread继承自Thread类,本质是一个线程。这里调用到它的start方法开启线程会走到HandlerThread的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实例对象,并和sThreadLocal相关联,接着通过Looper.myLooper()方法获取到刚才创建的Looper实例对象,并赋值给mLooper,最后调用到Looper.loop()方法进行循环。注意这是在子线程中!
我们回到IntentService的onCreate方法接着往下看,代码中调用到thread.getLooper()方法获取到刚赋值的mLooper,也就是我们之前创建的Looper实例对象,赋值给mServiceLooper,接着创建了一个ServiceHandler实例对象,将mServiceLooper作为参数传入。ServiceHandler是什么东东呢?我们去看下:
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);
}
}
可以看到ServiceHandler本身就是一个Handler,在这里重写了handleMessage方法,用来处理消息。
到此为止,IntentService的onCreate方法就分析完毕了,Service开启后,后续肯定会走到onStartCommand方法,我们跟进去看下:
/**
* 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;
}
在onStartCommand方法中又调用到onStart方法,直接将intent参数和startId参数传入,我们接着往下跟:
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
可以看到,在onStart方法中首先获取到一个Message对象,分别将startId和intent赋值给msg.arg1和msg.obj,最后借助mServiceHandler将msg消息发送出去。接下来肯定会走到mServiceHandler的handleMessage方法中,我们一起去看下:
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);
}
}
注意,由于我们在IntentService的onCreate方法中,在HandlerThread工作线程的run方法中调用的Looper.loop(),所以handleMessage方法在这里是运行在子线程中的!!!可以看到在handleMessage方法中首先调用到了onHandleIntent方法,接着调用stopSelf方法关闭当前Service。onHandleIntent方法是个抽象方法,我们创建IntentService的时候不正是实现了onHandleIntent方法来直接处理耗时操作的吗哈哈,耗时操作处理完毕后,handleMessage方法中后续会调用stopSelf方法来关闭当前Service。
有关IntentService的分析到这里就结束了,欢迎大家点我小心心啊哈哈。