IntentService 介绍
IntentService 是一种特殊的 Service,它继承了 Service 并且它是一个抽象类,因此必须创建它的子类才能够使用 IntentService。它可用于执行后台耗时任务,当任务执行完成后它会自动停止,在资源不足时,系统会对一些被认为时无用的资源给清理掉,由于它是 Service 的原因,它的优先级比单纯的线程的优先级高很多,不容易被系统杀死(清理掉),所以它适合执行一些高优先级的后台任务。在实现上,IntentService 封装了 Handlerhread 和 Handler。
HandlerThread 继承了 Thread,它是一种可以使用 Handler 的 Thread。它的实现是通过在run()方法中通过Looper.prepare()来创建消息队列,并通过Looper.loop()方法来开启消息循环, 它的内部对Thread 的 run 方法进行重写,通过Handler的消息方式(Looper循环)来通知HandlerThread执行一个具体的任务。
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
在明确了不需要使用HandlerThread的时,可以通过它的quit或者quitSafely方法来终止线程的执行
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
这两个方法的区别是:
quit()
使用此方法可能是不安全的,因为在Looper队列终止之前可能无法传递某些消息。
quitSafely()
使用此方法可能是安全的,因为一旦已经传递消息,队列中的所有剩余消息被处理,方法就会终止。然而,在循环终止之前,延迟的消息将在未来的到期时间内不传递。
从源码来分析 IntentService 的执行顺序
在onCreate()初始化HandlerThread和ServiceHandler,用于在后面调用onStart后来发送消息。
@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);
}
每次启动服务都会调用一次onStartCommand()方法,并且它会调用onStart()
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
在onStart()中发送消息
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
后台任务是顺序执行的
因为 Handler 中的 Looper 是顺序处理消息。
任务执行完成之后结束服务:
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); 而不使用 stopSelf();
// 是因为 stopSelf() 会立即停止服务,
// 而 stopSelf(msg.arg1); 在停止服务前会先判断最近启动服务的次数是否和 startId 相等
// 如果相等就历经停止服务,不想动则不停止服务
stopSelf(msg.arg1);
}
}
IntentService 使用
创建一个实例继承自 IntentService
public class TestIntentService extends IntentService {
private static final String TAG = "TestIntentService";
public TestIntentService() {
super(TAG);
Log.e(TAG, "TestIntentService: " );
}
@Override
public void onCreate() {
super.onCreate();
Log.e(TAG, "onCreate: " );
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
String taskAction = intent.getStringExtra("task_action");
SystemClock.sleep(3000);
Log.e(TAG, "onHandleIntent: "+taskAction);
}
@Override
public void onDestroy() {
Log.e(TAG, "onDestroy: service destory" );
super.onDestroy();
}
}
注册服务
在AndroidMainfest.xml中注册服务
开启服务
Intent intent = new Intent(CallBackTestActivity.this, TestIntentService.class);
intent.putExtra("task_action","com.dx.action.TASK1");
// 开启第一个服务
startService(intent);
intent.putExtra("task_action","com.dx.action.TASK2");
// 开启第二个服务
startService(intent);
intent.putExtra("task_action","com.dx.action.TASK3");
// 开启第三个服务
startService(intent);
输出结果是:
从截图中的时间,以及输出顺序正好验证了上面的叙述!ok,完工~
原创作者:龙衣袭,原文链接:https://www.jianshu.com/p/92c8a4451bb0