轉(zhuǎn)載請(qǐng)注明出處:http://www.lxweimin.com/p/95e0ef1b81cb
最近正在加深基礎(chǔ),看到個(gè)IntentService類,以前從來沒有遇見過,更不知其用來干嘛的,所以就整理了一個(gè)demo,看看這個(gè)怎么使用。
我們經(jīng)常用到Service,并且在Service開啟線程處理耗時(shí)操作,Android封裝了一個(gè)IntentService類,該類已經(jīng)幫我們創(chuàng)建好了線程供我們使用。
1 簡介
IntentService概括
IntentService is a base class for Service that handle asynchronous requests (expressed as Intents) on demand. Clients send requests through startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.
This "work queue processor" pattern is commonly used to offload tasks from an application's main thread. The IntentService class exists to simplify this pattern and take care of the mechanics. To use it, extend IntentService and implement onHandleIntent(Intent). IntentService will receive the Intents, launch a worker thread, and stop the service as appropriate.
All requests are handled on a single worker thread -- they may take as long as necessary (and will not block the application's main loop), but only one request will be processed at a time.
IntentService是Service的子類,根據(jù)需要處理異步請(qǐng)求(以intent表示)。客戶端通過調(diào)用startService(Intent) 發(fā)送請(qǐng)求,該Service根據(jù)需要啟動(dòng),使用工作線程處理依次每個(gè)Intent,并在停止工作時(shí)停止自身。
這種“工作隊(duì)列處理器”模式通常用于從應(yīng)用程序的主線程中卸載任務(wù)。 IntentService類的存在是為了簡化這種模式。 要使用它,擴(kuò)展IntentService并實(shí)現(xiàn)onHandleIntent(Intent)。 IntentService將收到Intents,啟動(dòng)一個(gè)工作線程,并根據(jù)需要停止該服務(wù)。
所有請(qǐng)求都在單個(gè)工作線程處理 - 它們可能需要很長的時(shí)間(并且不會(huì)阻止應(yīng)用程序的主循環(huán)),但是一次只會(huì)處理一個(gè)請(qǐng)求。
2 代碼
在IntentService中處理下載請(qǐng)求(模擬),并將進(jìn)度更新到Ui。
MyIntentService.java代碼如下:
public class MyIntentService extends IntentService {
private final static String TAG = "MyIntentService";
public static final String ACTION_DOWN_IMG = "down.image";
public static final String ACTION_DOWN_VID = "down.vid";
public static final String ACTION_DOWN_PROGRESS = "com.zpengyong.down.progress";
public static final String ACTION_SERVICE_STATE = "com.zpengyong.service.state";
public static final String PROGRESS = "progress";
public static final String SERVICE_STATE = "service_state";
//構(gòu)造方法 一定要實(shí)現(xiàn)此方法否則Service運(yùn)行出錯(cuò)。
public MyIntentService() {
super("MyIntentService");
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate");
sendServiceState("onCreate");
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.i(TAG, "");
}
@Override
protected void onHandleIntent(Intent intent) {
Log.i(TAG, "onHandleIntent thread:"+Thread.currentThread());
String action = intent.getAction();
if(action.equals(ACTION_DOWN_IMG)){
for(int i = 0; i < 100; i++){
try{ //模擬耗時(shí)操作
Thread.sleep(50);
}catch (Exception e) {
}
sendProgress(i);
}
}else if(action.equals(ACTION_DOWN_VID)){
for(int i = 0; i < 100; i++){
try{ //模擬耗時(shí)操作
Thread.sleep(70);
}catch (Exception e) {
}
sendProgress(i);
}
}
Log.i(TAG, "onHandleIntent end");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy");
sendServiceState("onDestroy");
}
//發(fā)送Service的狀態(tài)
private void sendServiceState(String state){
Intent intent = new Intent();
intent.setAction(ACTION_SERVICE_STATE);
intent.putExtra(SERVICE_STATE, state);
sendBroadcast(intent);
}
//發(fā)送進(jìn)度
private void sendProgress(int progress){
Intent intent = new Intent();
intent.setAction(ACTION_DOWN_PROGRESS);
intent.putExtra(PROGRESS, progress);
sendBroadcast(intent);
}
}
使用IntentService的方法:
- 繼承IntentService。
- 實(shí)現(xiàn)不帶參數(shù)的構(gòu)造方法,并且調(diào)用父類IntentService的構(gòu)造方法。
- 實(shí)現(xiàn)onHandleIntent方法。
在onHandleIntent方法中可以根據(jù)intent來區(qū)分任務(wù),這里有兩個(gè)任務(wù),一個(gè)是下載圖片、一個(gè)是下載視頻(模擬耗時(shí)操作)。
運(yùn)行效果
1 只點(diǎn)擊“啟動(dòng)任務(wù)一”。
打印:
07-15 03:07:24.589: I/MyIntentService(3186): onCreate
07-15 03:07:24.593: I/MyIntentService(3186): onHandleIntent thread:Thread[IntentService[MyIntentService],5,main]
07-15 03:07:30.918: I/MyIntentService(3186): onHandleIntent end
07-15 03:07:31.017: I/MyIntentService(3186): onDestroy
IntentService啟動(dòng)后再onHandleIntent方法中執(zhí)行任務(wù)(該方法工作在子線程中),任務(wù)執(zhí)行完后,IntentService銷毀。
2 點(diǎn)擊“啟動(dòng)任務(wù)一”,任務(wù)未完成時(shí)點(diǎn)擊“停止Service”。
log
07-15 03:08:08.477: I/MyIntentService(3186): onCreate
07-15 03:08:08.478: I/MyIntentService(3186): onHandleIntent thread:Thread[IntentService[MyIntentService],5,main]
07-15 03:08:12.203: I/MyIntentService(3186): onDestroy
07-15 03:08:14.253: I/MyIntentService(3186): onHandleIntent end
IntentService中線程執(zhí)行任務(wù)時(shí),stopService會(huì)讓IntentService銷毀,但是任務(wù)繼續(xù)執(zhí)行,直到執(zhí)行完成線程退出。
3 點(diǎn)擊“啟動(dòng)任務(wù)一”,任務(wù)完成后點(diǎn)擊“啟動(dòng)任務(wù)二”。
log信息:
07-15 03:11:42.366: I/MyIntentService(3186): onCreate
07-15 03:11:42.367: I/MyIntentService(3186): onHandleIntent thread:Thread[IntentService[MyIntentService],5,main]
07-15 03:11:48.285: I/MyIntentService(3186): onHandleIntent end
07-15 03:11:48.289: I/MyIntentService(3186): onDestroy
07-15 03:11:50.174: I/MyIntentService(3186): onCreate
07-15 03:11:50.205: I/MyIntentService(3186): onHandleIntent thread:Thread[IntentService[MyIntentService],5,main]
07-15 03:11:58.446: I/MyIntentService(3186): onHandleIntent end
07-15 03:11:58.510: I/MyIntentService(3186): onDestroy
由上可知,任務(wù)執(zhí)行完成后,線程退出循環(huán),Service銷毀。重新開啟任務(wù)則重新創(chuàng)建Service,執(zhí)行任務(wù)。
4 點(diǎn)擊“啟動(dòng)任務(wù)一”,任務(wù)完成前點(diǎn)擊“啟動(dòng)任務(wù)二”。
log信息
07-15 03:16:46.998: I/MyIntentService(3186): onCreate
07-15 03:16:46.998: I/MyIntentService(3186): onHandleIntent thread:Thread[IntentService[MyIntentService],5,main]
07-15 03:16:52.980: I/MyIntentService(3186): onHandleIntent end
07-15 03:16:52.980: I/MyIntentService(3186): onHandleIntent thread:Thread[IntentService[MyIntentService],5,main]
07-15 03:17:01.048: I/MyIntentService(3186): onHandleIntent end
07-15 03:17:01.053: I/MyIntentService(3186): onDestroy
正常startService啟動(dòng)兩個(gè)任務(wù),第一個(gè)未完成前,將第二個(gè)任務(wù)放到隊(duì)列中,等待第一個(gè)完成后執(zhí)行第二個(gè)任務(wù),第二個(gè)任務(wù)完成后,Service自動(dòng)銷毀。
5 點(diǎn)擊“啟動(dòng)任務(wù)一”,任務(wù)完成前點(diǎn)擊“停止Service”,然后再點(diǎn)擊“啟動(dòng)任務(wù)二”。
log信息
第一個(gè)任務(wù)尚未結(jié)束時(shí)stopservice,IntentService銷毀,其線程繼續(xù)運(yùn)行(tid 3691)。此時(shí)重新startService會(huì)開啟IntentService,其會(huì)重新創(chuàng)建一個(gè)線程運(yùn)行任務(wù)(tid 3692)。兩個(gè)任務(wù)在兩個(gè)線程中運(yùn)行,所以其執(zhí)行完的先后順序不確定。
3 IntentService源碼解析
路徑:frameworks/base/core/java/android/app/IntentService.java
先看下IntentService的構(gòu)造方法和onCreate()。
public abstract class IntentService extends Service {
//Creates an IntentService. Invoked by your subclass's constructor.
public IntentService(String name) {
super();
mName = name;
}
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
。。。。
}
IntentService 是繼承Service的一個(gè)抽象類,所以需要繼承IntentService 并必須實(shí)現(xiàn)其抽象方法onHandleIntent。
繼承IntentService需要實(shí)現(xiàn)一個(gè)空的構(gòu)造器,并且調(diào)用IntentService的構(gòu)造器。
在onCreate()方法中創(chuàng)建了一個(gè)HandlerThread,并允許該線程。HandlerThread 不太懂的可以參考我的上一篇文章Android HandlerThread詳解 。
獲取子線程中的Looper實(shí)例,然后創(chuàng)建與子線程綁定的Handler對(duì)象。
接著看IntentService的onStart()。
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
在onStart方法中,創(chuàng)建Message對(duì)象,并將“消息”通過mServiceHandler發(fā)送到子線程中的消息隊(duì)列中。
我們知道這些消息處理還是會(huì)分發(fā)到Handler中。接著看mServiceHandler
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);
}
}
消息會(huì)在handlerMessage中處理,該方法中調(diào)用了onHandleIntent,所以我們需要實(shí)現(xiàn)onHandleIntent,在該方法中做我們要做的任務(wù)。而消息處理完成后,調(diào)用stopSelf將自身Service銷毀。這里可能會(huì)有疑問,既然一個(gè)任務(wù)執(zhí)行完成后就會(huì)執(zhí)行stopSelf,那多個(gè)任務(wù)是怎么處理的呢?這里stopSelf(msg.arg1),會(huì)先看隊(duì)列中是否有消息待處理,如果有則繼續(xù)處理后面的消息,沒有才會(huì)將Service銷毀。
接著看IntentService的onDestroy方法
@Override
public void onDestroy() {
mServiceLooper.quit();
}
在IntentService的onDestroy方法中會(huì)調(diào)用looper的quit方法,將子線程的消息循環(huán)停止,等待任務(wù)完成后結(jié)束子線程。
4 總結(jié)
IntentService是一個(gè)比較便捷的類,省了我們?cè)趧?chuàng)建Thread,但是并不能適合所有的情況,它會(huì)創(chuàng)建一個(gè)線程,多個(gè)任務(wù)按順序執(zhí)行,并且執(zhí)行過程中不能夠取消該任務(wù)。所以還是需要根據(jù)情況進(jìn)行使用。