概述
Android中的Service是運(yùn)行在主線程(UI線程)访敌,如果要處理耗時(shí)任務(wù)凉敲,需要手動(dòng)創(chuàng)建工作線程,不然會(huì)有ANR的風(fēng)險(xiǎn)寺旺。IntentService繼承于Service爷抓,內(nèi)部使用工作線程來(lái)處理請(qǐng)求的任務(wù)。
使用
Step1. 定義IntentService的子類(lèi):傳入線程名稱(chēng)阻塑、重寫(xiě)onHandleIntent()
方法
public class MyIntentService extends IntentService {
public MyIntentService() {
// 傳入工作線程的名稱(chēng)
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
// 處理耗時(shí)任務(wù)
}
}
Step2. 在AndroidManifest.xml注冊(cè)
<service
android:name=".MyIntentService"
android:exported="false"/>
Step3. 發(fā)送任務(wù)請(qǐng)求
Intent intent = new Intent(context, MyIntentService.class);
context.startService(intent);
源碼分析
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
// onHandleIntent()方法在工作線程中執(zhí)行蓝撇,執(zhí)行完后調(diào)用stopSelf方法關(guān)掉Service
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
public IntentService(String name) {
super();
mName = name;
}
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@Override
public void onCreate() {
super.onCreate();
// 創(chuàng)建HandlerThread,這是一個(gè)工作線程陈莽,
// 因此使用IntentService渤昌,不用再額外創(chuàng)建子線程,就可以處理耗時(shí)任務(wù)
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
// 獲取工作線程的Looper
mServiceLooper = thread.getLooper();
// 將工作線程的Looper與Handler進(jìn)行綁定走搁,使其在工作線程中處理任務(wù)
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
// 將任務(wù)消息加入到工作隊(duì)列中
mServiceHandler.sendMessage(msg);
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onDestroy() {
mServiceLooper.quit();
}
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
stopSelf()和stopSelf(int startId)的區(qū)別:
在調(diào)用stopSelf(startId)時(shí)独柑,系統(tǒng)會(huì)檢測(cè)是否還有startId存在,如果存在私植,則不銷(xiāo)毀Service忌栅,否則銷(xiāo)毀Service。即stopSelf(startId)和onStartCommand()成對(duì)的時(shí)候曲稼,Service才被銷(xiāo)毀索绪。
在調(diào)用stopSelf()時(shí)湖员,實(shí)際調(diào)用的是stopSelf(-1),那么將直接銷(xiāo)毀Service者春,系統(tǒng)就不會(huì)檢測(cè)是否還有其他的startId存在破衔。
總結(jié):
從上面源碼可以看出清女,IntentService本質(zhì)是采用Handler和HandlerThread方式:
- 通過(guò)
HandlerThread
單獨(dú)開(kāi)啟一個(gè)線程钱烟; - 創(chuàng)建一個(gè)名為
ServiceHandler
的內(nèi)部Handler; - 將
ServiceHandler
與HandlerThread
所對(duì)應(yīng)的子線程進(jìn)行綁定嫡丙; - 通過(guò)
onStartCommand()
傳遞給服務(wù)的Intent拴袭,依次插入到工作隊(duì)列中,并逐個(gè)發(fā)送給onHandleIntent()
曙博; - 通過(guò)
onHandleIntent()
來(lái)依次處理所有Intent請(qǐng)求對(duì)象所對(duì)應(yīng)的任務(wù)拥刻。
使用場(chǎng)景
- 線程任務(wù)需要按順序,在后臺(tái)執(zhí)行的使用場(chǎng)景父泳,如:離線下載般哼。
- 由于所有的任務(wù)都在一個(gè)Thread Looper里面來(lái)做,所以不適合多個(gè)數(shù)據(jù)同時(shí)請(qǐng)求的場(chǎng)景惠窄。
對(duì)比
IntentService與Service的區(qū)別
- Service依賴于應(yīng)用程序的主線程蒸眠,所以不宜在Service中編寫(xiě)耗時(shí)的邏輯和操作,否則會(huì)引起ANR杆融;IntentService創(chuàng)建一個(gè)工作線程來(lái)處理任務(wù)楞卡。
- Service需要主動(dòng)調(diào)用
stopSelf()
來(lái)結(jié)束服務(wù),而IntentService不需要(在所有Intent處理完后脾歇,系統(tǒng)會(huì)自動(dòng)關(guān)閉服務(wù))蒋腮。
IntentService與其他線程的區(qū)別
- IntentService內(nèi)部采用HandlerThread實(shí)現(xiàn),作用類(lèi)似于后臺(tái)線程藕各。
- 與后臺(tái)線程相比池摧,IntentService是一種后臺(tái)服務(wù),優(yōu)勢(shì)是:優(yōu)先級(jí)高激况,不易被系統(tǒng)殺死作彤,從而保證任務(wù)的執(zhí)行。(對(duì)于后臺(tái)線程誉碴,若進(jìn)程中沒(méi)有活動(dòng)的四大組件宦棺,則該線程的優(yōu)先級(jí)非常低,容易被系統(tǒng)殺死黔帕,無(wú)法保證任務(wù)的執(zhí)行代咸。)