Android日记之IntentService源码解析
前言
ServiceIntent是Service和Handler两个合在一起进行再次封装的类,可以实现在Service里面直接进行异步的操作,因为如果是直接在Service进行耗时操作的话,是很容易造成ANR的,所以这时候我们就需要这个ServiceIntent这个类的,使用方法在我的Android日记之Service这篇文章中已经讲述了,这里就不在赘述。
IntentService源代码
package android.app;
import android.annotation.WorkerThread;
import android.annotation.Nullable;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
//实例化一个内部类ServiceHandler
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
//创建一个内部类来ServiceHandler继承Handler
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
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);
}
IntentService的源码很短,通过观察发现,里面其实是对HandlerThread进行了再次的封装,首先我们也发现,它是一个抽象类,这就需要我们去继承他然后去进行使用,因为它是继承Service的,所以它的生命周期方法是相同的,我们接下来来就按着生命周期一步一步的来看。
onCreate()生命周期
@Override
public void onCreate() {
super.onCreate();
//这里创建了一个HandlerThread
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
首先是onCreate()
方法,这里首先创建了一个HandlerThread,参数为你自己指定的名称,接来来开启了一个带有轮询器Looper的线程,然后还创建了一个用来处理异步操作的Handler。
//ServiceHandler是一个内部类,继承了Handler
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就可以通过轮询来进行异步的耗时任务的操作,这里有几个关注的点,从代码里看出,ServiceHandler用的Looper其实是ThreadHandler的Looper,而HandlerThread的Looper是子线程的轮询器,MessageQueue也是ThreadHandler的消息队列,也就是说ServiceHandler的handlerMessage()
也是执行在子线程中的,不是运行在主线程上的。
onStartCommand()生命周期
@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 onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
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);
}
}
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
这里先调用了onStart()
的方法,通过ServiceHandler构建了一个Message,然后通过传进来的Intent和startId赋值到Message里面去,最后通过ServiceHandler将消息发送出去,最后被HandleMessage接收并通过onHandleIntent()
进行处理,这个方法是一个抽象方法,由我们自己去写需要处理的逻辑来进行耗时的操作。
当执行完毕后就会执行stopSelf()
,这时候服务就会自动停止了。stopSelf()
有两种重载方法,一个可以接收参数的,另一种是不接收参数的,区别在于,如果有传参数的话,则会把所有子线程待处理的任务全部处理后才会停止服务,没有传的话,就是执行完整个任务就直接停止了,后面的待任务也就不处理了。
onBind()和onDestroy()
@Override
public void onDestroy() {
mServiceLooper.quit();
}
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
onDestory()
没什么好说的,停止服务的时候进行调用,然后退出这个Looper轮询器,主要讲一讲onBind()
整个方法,源码这里返回的是null,意思就是Google是不建议通过绑定的方式去使用IntentService,因为如果执行要使用绑定的方法去使用Service的的话,那么onHandleIntent()
就不会被回调了,因为它是在onStartCommand()
里的,这样子使用的话就和普通的Service没什么区别了。