為什么我們需要IntentService ?
Android中的IntentService是繼承自Service類的,在我們討論IntentService之前叨叙,我們先想一下Service的特點(diǎn): Service的回調(diào)方法(onCreate喘帚、onStartCommand垫竞、onBind郑原、onDestroy)都是運(yùn)行在主線程中的漓藕。當(dāng)我們通過startService啟動(dòng)Service之后砸喻,我們就需要在Service的onStartCommand方法中寫代碼完成工作柔逼,但是onStartCommand是運(yùn)行在主線程中的,如果我們需要在此處完成一些網(wǎng)絡(luò)請(qǐng)求或IO等耗時(shí)操作割岛,這樣就會(huì)阻塞主線程UI無響應(yīng)愉适,從而出現(xiàn)ANR現(xiàn)象。為了解決這種問題癣漆,最好的辦法就是在onStartCommand中創(chuàng)建一個(gè)新的線程维咸,并把耗時(shí)代碼放到這個(gè)新線程中執(zhí)行。由此看來惠爽,創(chuàng)建一個(gè)帶有工作線程的Service是一種很常見的需求(因?yàn)楣ぷ骶€程不會(huì)阻塞主線程)癌蓖,所以Android為了簡(jiǎn)化開發(fā)帶有工作線程的Service,Android額外開發(fā)了一個(gè)類——–IntentService婚肆。
IntentService的特點(diǎn)
- 獨(dú)立的線程
onCreate租副、onStartCommand、onDestroy回調(diào)方法都是運(yùn)行在主線程中的较性,而onHandleIntent是運(yùn)行在工作線程IntentService中的用僧。 - 自動(dòng)創(chuàng)造一個(gè)隊(duì)列處理事務(wù)
當(dāng)我們通過startService多次啟動(dòng)了IntentService,這會(huì)產(chǎn)生多個(gè)job赞咙,由于IntentService只持有一個(gè)工作線程责循,所以每次onHandleIntent只能處理一個(gè)job。面多多個(gè)job人弓,IntentService會(huì)如何處理沼死?處理方式是one-by-one,也就是一個(gè)一個(gè)按照先后順序處理崔赌,先將intent1傳入onHandleIntent意蛀,讓其完成job1耸别,然后將intent2傳入onHandleIntent,讓其完成job2…這樣直至所有job完成县钥,所以我們IntentService不能并行的執(zhí)行多個(gè)job秀姐,只能一個(gè)一個(gè)的按照先后順序完成,當(dāng)所有job完成的時(shí)候IntentService就銷毀了若贮,會(huì)執(zhí)行onDestroy回調(diào)方法省有。 - 當(dāng)所有的請(qǐng)求處理完之后,自動(dòng)銷毀谴麦,不用調(diào)用 stopSelf()
- 自動(dòng) onBind 返回 null
- 只要將需要處理的事務(wù)放在onHandleIntent()蠢沿,F(xiàn)ramework會(huì)回調(diào)其onHandleIntent方法。
- 在service構(gòu)造函數(shù)要返回super(“ServiceName”);
IntentService的使用
MainActivity
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent bindIntent = new Intent(this, MyIntentService.class);
bindIntent.putExtra("name","task1");
startService(bindIntent);
bindIntent.putExtra("name","task2");
startService(bindIntent);
bindIntent.putExtra("name","task2");
startService(bindIntent);
}
}
MyIntentService
public class MyIntentService extends IntentService {
String Tag = "MyIntentService";
public MyIntentService() {
super("MyIntentService");
Log.i(Tag, "MyIntentService構(gòu)造函數(shù), Thread: " + Thread.currentThread().getName());
}
@Override
public void onCreate() {
super.onCreate();
Log.i(Tag, "MyIntentService -> onCreate, Thread: " + Thread.currentThread().getName());
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
Log.i(Tag, "MyIntentService -> onStartCommand, Thread: " + Thread.currentThread().getName() + " , startId: " + startId);
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(Tag, "MyIntentService -> onDestroy, Thread: " + Thread.currentThread().getName());
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
String name = intent.getStringExtra("name");
//執(zhí)行下載任務(wù)匾效,無法新開線程舷蟀;
Log.i(Tag, "MyIntentService -> onHandleIntent, Thread: " + Thread.currentThread().getName() + ", 《" + name + "》任務(wù)完成");
}
}
結(jié)果
06-24 03:18:09.819 27760-27760/? I/MyIntentService: MyIntentService構(gòu)造函數(shù), Thread: main
06-24 03:18:09.819 27760-27760/? I/MyIntentService: MyIntentService -> onCreate, Thread: main
06-24 03:18:09.819 27760-27760/? I/MyIntentService: MyIntentService -> onStartCommand, Thread: main , startId: 1
06-24 03:18:09.819 27760-27760/? I/MyIntentService: MyIntentService -> onStartCommand, Thread: main , startId: 2
06-24 03:18:09.819 27760-27760/? I/MyIntentService: MyIntentService -> onStartCommand, Thread: main , startId: 3
06-24 03:18:09.820 27760-27781/? I/MyIntentService: MyIntentService -> onHandleIntent, Thread: IntentService[MyIntentService], 《task1》任務(wù)完成
06-24 03:18:09.820 27760-27781/? I/MyIntentService: MyIntentService -> onHandleIntent, Thread: IntentService[MyIntentService], 《task2》任務(wù)完成
06-24 03:18:09.820 27760-27781/? I/MyIntentService: MyIntentService -> onHandleIntent, Thread: IntentService[MyIntentService], 《task2》任務(wù)完成
06-24 03:18:10.166 27760-27760/? I/MyIntentService: MyIntentService -> onDestroy, Thread: main
通過以上的輸出結(jié)果我們可以發(fā)現(xiàn),MyIntentService的onCreate面哼、onStartCommand野宜、onDestroy回調(diào)方法都是運(yùn)行在主線程main中的,而onHandleIntent是運(yùn)行在工作線程IntentService[MyIntentService]中的魔策,這驗(yàn)證了我們上面所說的IntentService的第一個(gè)和第二個(gè)特點(diǎn)匈子。
通過上面的輸出結(jié)果我們還會(huì)發(fā)現(xiàn),在我們連續(xù)調(diào)用了三次startService(intent)之后闯袒,onStartCommand依次被調(diào)用了三次虎敦,然后依次執(zhí)行了onHandleIntent三次,這樣就依次完成了job搁吓,當(dāng)最后一個(gè)job完成原茅,也就是在最后一次onHandleIntent調(diào)用完成之后,整個(gè)IntentService的工作都完成堕仔,執(zhí)行onDestroy回調(diào)方法擂橘,IntentService銷毀。
IntentService源碼分析
intentservice = HandlerThread + Service
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) {
//在工作線程中調(diào)用onHandleIntent摩骨,確保onHandleIntent不會(huì)阻塞主線程
onHandleIntent((Intent)msg.obj);
//在執(zhí)行完了onHandleIntent之后通贞,我們需要調(diào)用stopSelf(startId)聲明某個(gè)job完成了
//當(dāng)所有job完成的時(shí)候,Android就會(huì)回調(diào)onDestroy方法恼五,銷毀IntentService
stopSelf(msg.arg1);
}
}
public IntentService(String name) {
//此處的name將用作線程名稱
super();
mName = name;
}
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@Override
public void onCreate() {
super.onCreate();
//創(chuàng)建HandlerThread昌罩,利用mName作為線程名稱,HandlerThread是IntentService的工作線程
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
//將創(chuàng)建的HandlerThread所綁定的looper對(duì)象傳遞給ServiceHandler灾馒,
//這樣我們創(chuàng)建的Handler就和HandlerThread通過消息隊(duì)列綁定在了一起
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(Intent intent, int startId) {
//在此方法中創(chuàng)建Message對(duì)象茎用,并將intent作為Message的obj參數(shù),
//這樣Message與Intent就關(guān)聯(lián)起來了
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
//將關(guān)聯(lián)了Intent信息的Message發(fā)送給Handler
mServiceHandler.sendMessage(msg);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//IntentService重寫了onStartCommand回調(diào)方法:在內(nèi)部調(diào)用onStart回調(diào)方法
//所以我們?cè)诶^承IntentService時(shí),不應(yīng)該再覆寫該方法,即便覆蓋該方法轨功,我們也應(yīng)該調(diào)用super.onStartCommand()
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onDestroy() {
//在onDestroy方法中調(diào)用了Handler的quit方法旭斥,該方法會(huì)終止消息循環(huán)
mServiceLooper.quit();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
protected abstract void onHandleIntent(Intent intent);
}