前言
-
多線程的應(yīng)用在Android開發(fā)中是非常常見的幔崖,常用方法主要有:
- 繼承Thread類
- 實(shí)現(xiàn)Runnable接口
- AsyncTask
- Handler
- HandlerThread
- IntentService
今天拦惋,我將主要介紹多線程
IntentService
的工作原理 & 源碼分析秽之。
Carson帶你學(xué)多線程系列
基礎(chǔ)匯總
Android多線程:基礎(chǔ)知識(shí)匯總
基礎(chǔ)使用
Android多線程:繼承Thread類使用(含實(shí)例教程)
Android多線程:實(shí)現(xiàn)Runnable接口使用(含實(shí)例教程)
復(fù)合使用
Android 多線程:AsyncTask使用教程(含實(shí)例講解)
Android 多線程:AsyncTask原理及源碼分析
Android多線程:HandlerThread使用教程(含實(shí)例講解)
Android多線程:HandlerThread原理及源碼分析
Android多線程:IntentService使用教程(含實(shí)例講解)
Android多線程:IntentService的原理及源碼分析
Android多線程:線程池ThreadPool全方位教學(xué)
相關(guān)使用
Android異步通信:這是一份全面&詳細(xì)的Handler機(jī)制學(xué)習(xí)攻略
Android多線程:手把手教你全面學(xué)習(xí)神秘的Synchronized關(guān)鍵字
Android多線程:帶你了解神秘的線程變量 ThreadLocal
目錄
1. 定義
Android
里的一個(gè)封裝類稚配,繼承四大組件之一的Service
2. 作用
處理異步請(qǐng)求 & 實(shí)現(xiàn)多線程
3. 使用場景
線程任務(wù) 需 按順序、在后臺(tái)執(zhí)行
- 最常見的場景:離線下載
- 不符合多個(gè)數(shù)據(jù)同時(shí)請(qǐng)求的場景:所有的任務(wù)都在同一個(gè)
Thread looper
里執(zhí)行
4. 工作原理
4.1 流程示意圖
-
IntentService
的工作原理 & 源碼工作流程如下:
4.2 特別注意
若啟動(dòng)IntentService
多次垦细,那么 每個(gè)耗時(shí)操作 則 以隊(duì)列的方式 在 IntentService
的 onHandleIntent
回調(diào)方法中依次執(zhí)行捺典,執(zhí)行完自動(dòng)結(jié)束
接下來,我們將通過 源碼分析 解決以下問題:
-
IntentService
如何單獨(dú)開啟1個(gè)新的工作線程 -
IntentService
如何通過onStartCommand()
將Intent 傳遞給服務(wù) & 依次插入到工作隊(duì)列中
5. 源碼分析
問題1:IntentService如何單獨(dú)開啟1個(gè)新的工作線程
主要分析內(nèi)容 = IntentService
源碼中的 onCreate()
方法
@Override
public void onCreate() {
super.onCreate();
// 1. 通過實(shí)例化andlerThread新建線程 & 啟動(dòng)大州;故 使用IntentService時(shí)续语,不需額外新建線程
// HandlerThread繼承自Thread,內(nèi)部封裝了 Looper
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
// 2. 獲得工作線程的 Looper & 維護(hù)自己的工作隊(duì)列
mServiceLooper = thread.getLooper();
// 3. 新建mServiceHandler & 綁定上述獲得Looper
// 新建的Handler 屬于工作線程 ->>分析1
mServiceHandler = new ServiceHandler(mServiceLooper);
}
/**
* 分析1:ServiceHandler源碼分析
**/
private final class ServiceHandler extends Handler {
// 構(gòu)造函數(shù)
public ServiceHandler(Looper looper) {
super(looper);
}
// IntentService的handleMessage()把接收的消息交給onHandleIntent()處理
@Override
public void handleMessage(Message msg) {
// onHandleIntent 方法在工作線程中執(zhí)行
// onHandleIntent() = 抽象方法厦画,使用時(shí)需重寫 ->>分析2
onHandleIntent((Intent)msg.obj);
// 執(zhí)行完調(diào)用 stopSelf() 結(jié)束服務(wù)
stopSelf(msg.arg1);
}
}
/**
* 分析2: onHandleIntent()源碼分析
* onHandleIntent() = 抽象方法疮茄,使用時(shí)需重寫
**/
@WorkerThread
protected abstract void onHandleIntent(Intent intent);
問題2:IntentService 如何通過onStartCommand() 將Intent 傳遞給服務(wù) & 依次插入到工作隊(duì)列中
/**
* onStartCommand()源碼分析
* onHandleIntent() = 抽象方法,使用時(shí)需重寫
**/
public int onStartCommand(Intent intent, int flags, int startId) {
// 調(diào)用onStart()->>分析1
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
/**
* 分析1:onStart(intent, startId)
**/
public void onStart(Intent intent, int startId) {
// 1. 獲得ServiceHandler消息的引用
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
// 2. 把 Intent參數(shù) 包裝到 message 的 obj 發(fā)送消息中根暑,
//這里的Intent = 啟動(dòng)服務(wù)時(shí)startService(Intent) 里傳入的 Intent
msg.obj = intent;
// 3. 發(fā)送消息力试,即 添加到消息隊(duì)列里
mServiceHandler.sendMessage(msg);
}
至此,關(guān)于IntentService
的源碼分析講解完畢排嫌。
6. 源碼總結(jié)
從上面源碼可看出:IntentService
本質(zhì) = Handler
+ HandlerThread
:
- 通過
HandlerThread
單獨(dú)開啟1個(gè)工作線程:IntentService
- 創(chuàng)建1個(gè)內(nèi)部
Handler
:ServiceHandler
- 綁定
ServiceHandler
與IntentService
- 通過
onStartCommand()
傳遞服務(wù)intent
到ServiceHandler
畸裳、依次插入Intent
到工作隊(duì)列中 & 逐個(gè)發(fā)送給onHandleIntent()
- 通過
onHandleIntent()
依次處理所有Intent
對(duì)象所對(duì)應(yīng)的任務(wù)
因此我們通過復(fù)寫
onHandleIntent()
& 在里面 根據(jù)Intent
的不同進(jìn)行不同線程操作 即可
7. 注意事項(xiàng)
此處,有兩個(gè)注意事項(xiàng)需要關(guān)注的:
- 工作任務(wù)隊(duì)列 = 順序執(zhí)行
- 不建議通過 bindService() 啟動(dòng) IntentService
注意事項(xiàng)1:工作任務(wù)隊(duì)列 = 順序執(zhí)行
即 若一個(gè)任務(wù)正在
IntentService
中執(zhí)行淳地,此時(shí)你再發(fā)送1個(gè)新的任務(wù)請(qǐng)求怖糊,這個(gè)新的任務(wù)會(huì)一直等待直到前面一個(gè)任務(wù)執(zhí)行完畢后才開始執(zhí)行
- 原因:
- 由于
onCreate()
只會(huì)調(diào)用一次 = 只會(huì)創(chuàng)建1個(gè)工作線程帅容; - 當(dāng)多次調(diào)用
startService(Intent)
時(shí)(即onStartCommand()
也會(huì)調(diào)用多次),其實(shí)不會(huì)創(chuàng)建新的工作線程伍伤,只是把消息加入消息隊(duì)列中 & 等待執(zhí)行并徘。 - 所以,多次啟動(dòng) IntentService 會(huì)按順序執(zhí)行事件
若服務(wù)停止嚷缭,則會(huì)清除消息隊(duì)列中的消息饮亏,后續(xù)的事件不執(zhí)行
注意事項(xiàng)2:不建議通過 bindService() 啟動(dòng) IntentService
原因:
// 在IntentService中,onBind()`默認(rèn)返回null
@Override
public IBinder onBind(Intent intent) {
return null;
}
- 采用
bindService()
啟動(dòng)IntentService
的生命周期如下:
onCreate() ->> onBind() ->> onunbind()->> onDestory()
- 即阅爽,并不會(huì)調(diào)用
onStart()
或onStartcommand()
路幸,故不會(huì)將消息發(fā)送到消息隊(duì)列,那么onHandleIntent()將不會(huì)回調(diào)付翁,即無法實(shí)現(xiàn)多線程的操作
此時(shí)简肴,你應(yīng)該使用
Service
,而不是IntentService
8. 對(duì)比
此處主要講解IntentService與四大組件Service百侧、普通線程的區(qū)別砰识。
8.1 與Service的區(qū)別
8.2 與其他線程的區(qū)別
9. 總結(jié)
- 本文主要 全面介紹了 多線程
IntentService
的工作原理 & 源碼分析 - 下一篇文章我將對(duì)講解
Android
多線程的相關(guān)知識(shí),感興趣的同學(xué)可以繼續(xù)關(guān)注Carson_Ho的簡書
Carson帶你學(xué)多線程系列
基礎(chǔ)匯總
Android多線程:基礎(chǔ)知識(shí)匯總
基礎(chǔ)使用
Android多線程:繼承Thread類使用(含實(shí)例教程)
Android多線程:實(shí)現(xiàn)Runnable接口使用(含實(shí)例教程)
復(fù)合使用
Android 多線程:AsyncTask使用教程(含實(shí)例講解)
Android 多線程:AsyncTask原理及源碼分析
Android多線程:HandlerThread使用教程(含實(shí)例講解)
Android多線程:HandlerThread原理及源碼分析
Android多線程:IntentService使用教程(含實(shí)例講解)
Android多線程:IntentService的原理及源碼分析
Android多線程:線程池ThreadPool全方位教學(xué)
相關(guān)使用
Android異步通信:這是一份全面&詳細(xì)的Handler機(jī)制學(xué)習(xí)攻略
Android多線程:手把手教你全面學(xué)習(xí)神秘的Synchronized關(guān)鍵字
Android多線程:帶你了解神秘的線程變量 ThreadLocal
歡迎關(guān)注Carson_Ho的簡書
不定期分享關(guān)于安卓開發(fā)的干貨佣渴,追求短辫狼、平、快辛润,但卻不缺深度膨处。