IntentService使用详解
之前已经学习过Android的四大组件之一Service,但是Service和前台运行在一个进程里,不能再Service中执行耗时操作,否则需要开启线程,执行完毕之后再借助Handler传回到主线程处理,Android提供了很多线程间通信的消息机制。
Google又进一步进行了封装,提供了IntentService,内部对Service和Handler进行了封装,做到用完即走,也不需要手动停止服务。更加方便,专注业务处理。IntentService的内部原理详见IntentService原理。
1、IntentService
IntentService类本身是一个抽象类,只有一个抽象方法onHandlerIntent(Intent intent),我们只需要继承IntentService,实现该方法,在该方法中执行耗时的任务即可。
protected abstract void onHandleIntent(@Nullable Intent intent);
1.1、继承IntentService
继承IntentService实现onHandlerIntent(Intent intent)方法。最好提供一个默认构造函数,调用父类构造函数。
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
//耗时业务写在这里
}
}
1.2、onHandlerIntent(Intent intent)
在onHandlerIntent(Intent intent)抽象方法中写后台逻辑,启动IntentService的时候,会自动启动该方法去执行。
@Override
protected void onHandleIntent(@Nullable Intent intent) {
//耗时业务写在这里
}
2、注册IntentService
别忘了自大组件都需要在AndroidManifest.xml中进行注册,否则无法使用。IntentService继承自Service也应当注册声明,否则无法启动IntentService。AndroidStudio对于未注册的IntentService也会提示:

<service
android:name=".MyIntentService"
android:enabled="true"
android:exported="false" />
3、启动IntentService
启动IntentService很简单,而且启动后不用管执行完毕自动关闭。
3.1、startService
和普通的Service一样直接通过startService()的方式启动
Intent intent = new Intent(context, MyIntentService.class);
context.startService(intent);
注意:不要使用bind绑定的方式启动IntentService,否则IntentService就会和普通Service一样,失去IntentService的作用了。
3.2、多次启动IntentService
多次启动 IntentService 不会重新创建新的服务和新的线程,只是把消息加入消息队列中等待执行。IntentService不能并行执行,只能一个一个按照先后顺序,当所有job完成的时候IntentService就销毁了,执行onDestroy回调方法。如果服务停止,会清除消息队列中的消息,后续的事件得不到执行。
4、IntentService源码
IntentService的内部原理详见《IntentService原理》。
4.1、方法执行流程
先来打印一下IntentService各个方法的执行顺序。

执行顺序:onCreate()->onStartCommand()->onStart()->onHandleIntent()
4.2、onHandlerIntent(Intent intent)
查看onHandlerIntent(Intent intent)源码可以看到,内部调用了onStart()方法
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
} 在继续看onStart()方法,这里给Handler发送了一个消息,而这个消息Message.obj携带的就是startService()的参数Intent
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
} 而这个mServiceHandler定义如下:
private volatile ServiceHandler mServiceHandler;
mServiceHandler在IntentService的onCreate()方法中通过HandlerThread线程的Looper进行初始化。关于Looper详见《Handler、Looper、MessageQueue消息机制原理》。
@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);
} 内部类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);
}
} 最终发现在Handler的handlerMessage()中,收到onStart()发送的消息,开始在Looper所在的子线程HandlerThread中执行onHandleIntent(Intent)方法