IntentService
简介
IntentService是一种特殊的Service,它继承了Service并且它是一个抽象类,因此必须创建它的子类才能去使用IntentService,IntentService可以用于执行后台耗时任务,而当任务执行完毕会自动停止,同时由于IntentService本身是Service的原因,所以其优先级是单纯的线程高很多,所以IntentService适合用于执行一些高优先级的后台任务。
在代码的实现上,IntentService封装了HandlerThread和Handler,在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);
}
当IntentService被第一次启动时,它的onCreate方法会被调用,onCreate方法会创建HandlerThread,然后使用它的Looper来构造一个Handler对象mServiceHandler,这样通过mServiceHandler发送的消息最终都会在HandlerThread中执行,从这个角度看,IntentService也可以用于执行后台任务,每次启动IntentService,它的onStartCommand方法就会调用一次,IntentService在onStartCommand中处理每一个后台任务的Intent。
从IntentService的onStartCommand方法中可以看出处理外界Intent的逻辑,代码如下。
@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);
}
从代码的实现可以看出,在OnStartCommand方法中,IntentServide通过构造Message对象,并设置obj为传入的intent,通过mServiceHandler发送信息,而这个信息会被HandlerThread中被处理。这个Intent对象的内容和外界startIntent(intent)中传入的intend对象的内容是完全一致的,并通过这个intent可以解析出外界启动IntentService所传入的参数,从而在onHandleIntent方法中处理。当onHandleIntent方法执行结束后,IntentService会通过stopSelf(int startId)方法来停止服务。
这里使用stopSelf(int startId)而不是stopSelf()来停止服务,是因为stopSelf()会立刻停止服务,这个时候可能会有其他消息还没被处理,而stopSelf(int startId)则会等待所有的信息都处理完毕后才终止服务,一般来说,stopSelf(int startId)在尝试定制服务之前会判断最近启动服务的id是否和startId相等,如果相等则立刻停止服务,否则不停止,在源码中的mActivityManager.stopServiceToken可以找到实现的策略。
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);
}
}
IntentService的onHandleIntent是一个抽象方法,它需要我们在子类中进行实现,它的作用是处理Intent参数并执行任务。如果当前只有一个后台任务,那么onHandleIntent在执行这个任务后,stopSelf(int startId)会立刻停止任务。如果当前存在多个任务,那么当onHandleIntent执行完最后一个任务后,stopSelf(int startId)才会停止任务。另外由于每执行一个后台任务就必须启动一次IntentService,而IntentService内部是通过消息的方式来向HandlerThread请求执行任务的,而Handler中的Looper是顺序处理消息的,所以可以得出,IntentService也是顺序执行后台任务的,所以当有多个后台任务同时存在的时候,这些后台任务会按照外界发起的顺序排队执行。
示例
public class LocalIntentService extends IntentService {
private static final String TAG = "LocalIntentService";
public LocalIntentService(String name) {
super(TAG);
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
String action = intent.getStringExtra("task_action");
Log.d(TAG, "receive task: " + action);
SystemClock.sleep(3000);
if ("TASK1".equals(action)) {
Log.d(TAG, "handle task: " + action);
}
}
@Override
public void onDestroy() {
Log.d(TAG, "service destory.");
super.onDestroy();
}
}
上面的代码中,在onHandleIntent中会对Intent中获取参数,然后根据不同的参数去执行不同的后台任务,而SystemClock.sleep(3000);
用于模拟耗时的方法,并在onDestory中打印日志,以验证IntentService停止的时机。下面是发起后台任务请求的代码。
for (int i = 0; i < 3; i++) {
Intent intent = new Intent(this, LocalIntentService.class);
intent.putExtra("task_action", "TASK" + (i + 1));
startService(intent);
}
以上的代码启动了三次LocalIntentService并传入不同的参数,日志如下所示。
06-21 17:58:16.681 27761-27805/com.daijie.intentserviceapp D/LocalIntentService: receive task: TASK1
06-21 17:58:19.682 27761-27805/com.daijie.intentserviceapp D/LocalIntentService: handle task: TASK1
06-21 17:58:19.683 27761-27805/com.daijie.intentserviceapp D/LocalIntentService: receive task: TASK2
06-21 17:58:22.684 27761-27805/com.daijie.intentserviceapp D/LocalIntentService: receive task: TASK3
06-21 17:58:25.686 27761-27761/com.daijie.intentserviceapp D/LocalIntentService: service destory.
从日志中可以看出,这三个后台任务是排队执行的,执行顺序根据他们发起请求时候的顺序,即TASK1->TASK2->TASK3,并且TASK3执行完后,LocalIntentService的onDestory被回调,服务被停止。
网友评论