原創文章,轉載請注意出處:http://blog.csdn.net/ruils/article/details/17251935
IntentService是一個很有意思的類,它的實現可以看成是命令設計模式。
如果對android Handler,Looper模型熟悉的話, IntentService就很好理解了。
IntentService繼承自Service,它把發過來的請求放在消息隊列中,按照隊列的順序在HandlerThread中一個一個處理,處理完畢則把自己Stop掉。
IntentService的用法很簡單,寫一個繼續它的子類,重寫onHandleIntent方法,然後死命的start這個service就可以了。
下面一步一步分析:
1.IntentService啓動時創建一個HandlerThread,並啓動它,然後用這個HandlerThread的looper,創建一個ServiceHandler. onCreate在IntentService的生命週期中,只會調用一次。
@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);
}
2. 有新的命令請求過來,就會把這個Intent放在消息列隊中。onStartCommand會在IntentService生命週期中調用一次或者多次。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
3. 所有發過來的請求都會發到這裏來處理,至於怎麼處理,就要自己重寫onHandleIntent這個虛方法了。處理完之後就會調用 stopSelf(msg.arg1)這個方法,這裏要注意,每處理完一個Intent就會Stop一次,但IntentService並不一定會被Stop掉,因爲這個stop方法帶有參數,只有消息隊列中沒有要處理的Intent了,IntentService纔會真正stop掉。
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);
}
}
protected abstract void onHandleIntent(Intent intent);
4.結束的時候,退出消息循環。
@Override
public void onDestroy() {
mServiceLooper.quit();
}
最後,IntentService有Redelivery模式,默認是關閉的,打開Redelivery模式後,它能保證最後一次發送的Intent命令能被完全執行到,即使IntentService掛掉了,也會重啓再執行。
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}