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中注册服务
<service android:name=".thread.TestIntentService"/>
开启服务
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,完工~