IntentService 介紹
IntentService 是一種特殊的 Service,它繼承了 Service 並且它是一個抽象類,因此必須創建它的子類才能夠使用 IntentService。它可用於執行後臺耗時任務,當任務執行完成後它會自動停止,在資源不足時,系統會對一些被認為時無用的資源給清理掉,由於它是 Service 的原因,它的優先級比單純的線程的優先級高很多,不容易被系統殺死(清理掉),所以它適合執行一些高優先級的後臺任務。在實現上,IntentService 封裝了 Handlerhread 和 Handler。
HandlerThread 繼承了 Thread,它是一種可以使用 Handler 的 Thread。它的實現是通過在run()方法中通過Looper.prepare()來創建消息隊列,並通過Looper.loop()方法來開啟消息循環, 它的內部對Thread 的 run 方法進行重寫,通過Handler的消息方式(Looper循環)來通知HandlerThread執行一個具體的任務。
<code>@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
/<code>
在明確了不需要使用HandlerThread的時,可以通過它的quit或者quitSafely方法來終止線程的執行
<code>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;
}
/<code>
這兩個方法的區別是:
quit()使用此方法可能是不安全的,因為在Looper隊列終止之前可能無法傳遞某些消息。
quitSafely()使用此方法可能是安全的,因為一旦已經傳遞消息,隊列中的所有剩餘消息被處理,方法就會終止。然而,在循環終止之前,延遲的消息將在未來的到期時間內不傳遞。
從源碼來分析 IntentService 的執行順序
在onCreate()初始化HandlerThread和ServiceHandler,用於在後面調用onStart後來發送消息。
<code>@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);
}
/<code>
每次啟動服務都會調用一次onStartCommand()方法,並且它會調用onStart()
<code>@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
/<code>
在onStart()中發送消息
<code>@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
/<code>
後臺任務是順序執行的因為 Handler 中的 Looper 是順序處理消息。
任務執行完成之後結束服務:
<code>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);
}
}
/<code>
IntentService 使用
創建一個實例繼承自 IntentService
<code>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();
}
}
/<code>
註冊服務在AndroidMainfest.xml中註冊服務
<code><service>
/<code>
開啟服務
<code>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);
/<code>
輸出結果是:
從截圖中的時間,以及輸出順序正好驗證了上面的敘述!ok,完工~
原創作者:龍衣襲,原文鏈接:https://www.jianshu.com/p/92c8a4451bb0
閱讀更多 程序員前線 的文章