IntentService是一种特殊的Service,他继承了Service并且它是一个抽象类,所以必须创建它的子类才能使用IntentService。IntentService可用于执行后台耗时任务,当任务执行完毕之后自动停止,由于IntentService是服务的原因,它的优先级要比单纯的线程要高,所以IntentService比较适合执行一些高优先级的任务,因为他优先级高,不容易被杀死。
从实现上来看,IntentService封装了HandlerThread和Handler。(HandlerThread是一个自带handler的线程,相比较于普通线程,完成了耗时操作使用主线程handler来通知主线程更新UI,HandlerThread需要别的线程使用它自带的handler来通知它执行任务。实现也非常简单,和上一篇handler机制中我们想要自定义一个子线程并且使用handler一样,只需要创建一个Loop,并启动它的消息循环即可,这里就不再展开了。)
@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);
}
当IntentService第一次启动以后,onCreate方法会创建一个HandlerThread,然后利用它Loop来创建一个mServiceHandler,这样通过mServiceHandler发送的消息都会交给HandlerThread来处理。每次启动IntentService都会调用它的startCommand方法,startCommand调用onStart。
@Override
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
可以看到IntentService通过mServiceHandler发送了一条消息,这个消息会被HandlerThread处理,mServiceHandler收到消息后会将intent传给onHandleIntent方法处理。注意这个intent对象和外界startService传递的intent是一样的,通过这个intent可以解析出外界传递给IntetnService的参数,通过这些参数就可以区分具体的后台任务,onHandleIntent就可以进行针对性的处理。执行完毕后,IntentService会通过stopSelf(startId)来尝试停止服务,如果此时还有别的消息未处理,stopSelf(startId)会等待全部处理完毕再关闭。(通过判断最近启动服务次数和startId是否相等)
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中的onHandleIntent方法需要我们继承之后自己实现,它可以区分intent中的参数来执行具体任务。每启动一次IntentService就等同于内部向HandlerThread发送一次请求,而Handler中的Looper是顺序执行任务的,所以intentService也是顺序执行后台任务的。
实现Demo:
public class MyIntentService extends IntentService {
private final static String TAG = "MyIntentService";
public MyIntentService() {
super(TAG);
}
@Override
protected void onHandleIntent(Intent intent) {
String action = intent.getStringExtra("task_action");
Log.i(TAG, "receive task :" + action);
SystemClock.sleep(3000);
if ("com.example.servicetest.TASK1".equals(action)) {
Log.i(TAG, "handle task :" + action);
}
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestory");
}
}
在onHandleIntent中睡眠3秒模拟耗时操作,然后区分"task_action"来执行具体任务。
主线程调用:
Intent service = new Intent(this, MyIntentService.class);
service.putExtra("task_action", "com.example.servicetest.TASK1");
startService(service);
service.putExtra("task_action", "com.example.servicetest.TASK2");
startService(service);
service.putExtra("task_action", "com.example.servicetest.TASK3");
startService(service);
要注意在AndroidManifest中注册service。
Log:
09-19 01:57:00.403 4472-4492/com.example.servicetest I/MyIntentService: receive task :com.example.servicetest.TASK1
09-19 01:57:03.414 4472-4492/com.example.servicetest I/MyIntentService: handle task :com.example.servicetest.TASK1
09-19 01:57:03.414 4472-4492/com.example.servicetest I/MyIntentService: receive task :com.example.servicetest.TASK2
09-19 01:57:06.424 4472-4492/com.example.servicetest I/MyIntentService: receive task :com.example.servicetest.TASK3
09-19 01:57:09.434 4472-4472/com.example.servicetest I/MyIntentService: onDestory
综上,IntentService是一个适合执行后台耗时操作的Service,自带消息循环机制,采用顺序的方式执行任务,可以启动多次,完成任务后自动停止。