Job任務(wù)是Android系統(tǒng)上非及時(shí)性任務(wù)的一種運(yùn)行機(jī)制院促,由系統(tǒng)根據(jù)使用者的條件設(shè)置統(tǒng)一管理運(yùn)行醋虏,有條件性,周期性谭胚,統(tǒng)一執(zhí)行徐块,延遲執(zhí)行等特性未玻;為移動(dòng)設(shè)備性能和功耗帶來良好收益。Google自Android M起引入JobScheduler概念胡控,建議非必要alarm操作用該模式替換扳剿,讓其JobService運(yùn)行的Job任務(wù)滿足條件后開始執(zhí)行,之后Andoroid的每一個(gè)版本都有該功能的增添昼激。主要設(shè)計(jì)思想是懶執(zhí)行概念庇绽,滿足必要條件才觸發(fā)執(zhí)行。
本文基于Android Q代碼介紹橙困。
本文檔閱讀時(shí)間50分鐘瞧掺,黑色字體可作為本文檔的簡讀版本。
1. Job任務(wù)執(zhí)行原理概覽
使用者構(gòu)建Job任務(wù)纷宇,把其構(gòu)建信息傳遞給Job任務(wù)管理系統(tǒng)夸盟;任務(wù)管理系統(tǒng)負(fù)責(zé)Job任務(wù)滿足條件的觸發(fā),Job任務(wù)相應(yīng)的執(zhí)行和生命周期管理像捶。
執(zhí)行模塊如下圖所示上陕,紫色區(qū)域代表Job任務(wù)使用者創(chuàng)建模塊,紅色區(qū)域代表Job任務(wù)系統(tǒng)管理模塊拓春,藍(lán)色區(qū)域代表Job任務(wù)狀態(tài)控制模塊释簿,綠色區(qū)域代表Job任務(wù)生命周期管理模塊的實(shí)現(xiàn)。
執(zhí)行功能主要由以下四個(gè)模塊組成硼莽,
- 調(diào)用者創(chuàng)建其相關(guān)的Job并傳遞給JobSchedulerService服務(wù)庶溶,一個(gè)Job任務(wù)由JobInfo的實(shí)例來描述,由唯一ID與JobService的實(shí)例一一綁定懂鸵,通過JobSchedulerService的對(duì)外暴露的接口函數(shù)schedule來把該Job任務(wù)傳遞到平臺(tái)層Framework的JobSchedulerService的服務(wù)中偏螺。
- Job任務(wù)的系統(tǒng)管理模塊,JobScheduleService服務(wù)是整個(gè)Job任務(wù)的中樞管理系統(tǒng)匆光,負(fù)責(zé)管理Job任務(wù)的執(zhí)行和重試套像,以及管理Job控制模塊和Job生命周期控制模塊。
- Job任務(wù)狀態(tài)控制模塊终息,當(dāng)條件狀態(tài)滿足后觸發(fā)Job的執(zhí)行夺巩。根據(jù)系統(tǒng)特性定義了一些Job的系統(tǒng)控制條件,當(dāng)狀態(tài)滿足控制條件時(shí)會(huì)更新JobStatus的狀態(tài)周崭,而后JobSchedulerService服務(wù)接到通知去執(zhí)行Job任務(wù)柳譬。
- Job任務(wù)生命周期控制模塊,該模塊是Job調(diào)用者需要運(yùn)行時(shí)對(duì)其運(yùn)行狀態(tài)的控制续镇。該模塊通過JobServiceContext類來實(shí)現(xiàn)美澳,該類是Job任務(wù)與調(diào)用者通信的橋梁(可跨進(jìn)程間調(diào)用),處理調(diào)用者JobService實(shí)例的綁定,啟動(dòng)人柿,執(zhí)行柴墩,停止忙厌,完成操作凫岖。
2. JobScheduler使用者
調(diào)用者使用JobScheduler時(shí),需構(gòu)建Job任務(wù)的相關(guān)構(gòu)造類為JobInfo逢净,其Buider類的參數(shù)為JobService的唯一ID和JobService的實(shí)現(xiàn)類的ComponentName哥放,調(diào)用者在Builder類里設(shè)置Job任務(wù)的相應(yīng)滿足條件,JobService的實(shí)現(xiàn)類包含了Job任務(wù)相應(yīng)的執(zhí)行或停止函數(shù)等實(shí)現(xiàn)爹土。
具體實(shí)現(xiàn)代碼如下例所示甥雕,
/** A JobService to clean up obsolete data in anomaly database */
// 定義一個(gè)繼承JobService的實(shí)現(xiàn)類,實(shí)現(xiàn)主要功能onStartJob和onStopJob函數(shù)
public class AnomalyCleanupJobService extends JobService{
private static final String TAG = "AnomalyCleanUpJobService";
@VisibleForTesting
static final long CLEAN_UP_FREQUENCY_MS = TimeUnit.DAYS.toMillis(1);
public static void scheduleCleanUp(Context context) {
//獲取JobScheduler服務(wù)胀茵。
final JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
final ComponentName component = new ComponentName(context, AnomalyCleanupJobService.class);
// 構(gòu)建JobInfo.Builder, 為該JobInfo設(shè)置滿足的執(zhí)行條件
final JobInfo.Builder jobBuilder =
new JobInfo.Builder(R.integer.job_anomaly_clean_up, component)
.setPeriodic(CLEAN_UP_FREQUENCY_MS)
.setRequiresDeviceIdle(true)
.setRequiresCharging(true)
.setPersisted(true);
final JobInfo pending = jobScheduler.getPendingJob(R.integer.job_anomaly_clean_up);
// Don't schedule it if it already exists, to make sure it runs periodically even after
// reboot
// 開啟Job任務(wù)的執(zhí)行
if (pending == null &&jobScheduler.schedule(jobBuilder.build())
!= JobScheduler.RESULT_SUCCESS) {
Log.i(TAG, "Anomaly clean up job service schedule failed.");
}
}
@Override
public boolean onStartJob(JobParameters params){
final BatteryDatabaseManager batteryDatabaseManager = BatteryDatabaseManager
.getInstance(this);
final BatteryTipPolicy policy = new BatteryTipPolicy(this);
ThreadUtils.postOnBackgroundThread(() -> {
batteryDatabaseManager.deleteAllAnomaliesBeforeTimeStamp(
System.currentTimeMillis() - TimeUnit.DAYS.toMillis(
policy.dataHistoryRetainDay));
// Job任務(wù)執(zhí)行完成后回調(diào)完成通知社露,設(shè)置是否重試
jobFinished(params, false /* wantsReschedule */);
})
return true;
}
@Override
public boolean onStopJob(JobParameters jobParameters){
return false;
}
}
JobInfo.Builder對(duì)其Job任務(wù)的條件限制大致類別如下:
周期時(shí)長,網(wǎng)絡(luò)狀態(tài)琼娘,時(shí)間(延遲時(shí)長峭弟,最遲運(yùn)行時(shí)長),重試方式脱拼,電池信息瞒瘸,contend URI更新等。
具體定義及使用可參考如下文檔熄浓,文檔已清晰介紹情臭,不再過多闡述,
https://developer.android.com/reference/android/app/job/JobInfo.Builder
3. Job任務(wù)系統(tǒng)服務(wù)管理模塊
3.1 Job任務(wù)系統(tǒng)管理服務(wù)模塊簡介
Job任務(wù)系統(tǒng)管理模塊是Job任務(wù)的核心模塊赌蔑,系統(tǒng)管理服務(wù)是Job任務(wù)功能的核心俯在;對(duì)使用者起著通訊及同步的作用,擔(dān)負(fù)著任務(wù)調(diào)用娃惯,任務(wù)執(zhí)行狀態(tài)開啟停止及完成跷乐;主要管理功能有如下:
- 控制Job的運(yùn)行數(shù)量JobConcurrencyManager(總體,后臺(tái)最小石景,后臺(tái)最大劈猿,根據(jù)內(nèi)存壓力配置數(shù)量組(ProcessStats.ADJ_MEM_FACTOR_*))。
- 接收調(diào)用者創(chuàng)建的Job潮孽,將數(shù)據(jù)存入到JobStore揪荣。
- 初始化Job的狀態(tài)控制模塊,將各個(gè)Job相應(yīng)的觸發(fā)條件分別更新到各個(gè)狀態(tài)控制模塊往史。
- 常量配置仗颈,可執(zhí)行Job數(shù)量,權(quán)重因子等。
- 創(chuàng)建平臺(tái)層Job任務(wù)為JobStatus(JobInfo為其構(gòu)造函數(shù)的首參數(shù))挨决,平臺(tái)層以此為來處理和維護(hù)Job请祖。
- Job任務(wù)的消息處理,執(zhí)行脖祈,過期肆捕,停止;UID狀態(tài)更新(包含change, gone, active, idle)盖高。
3.2 Job任務(wù)系統(tǒng)管理服務(wù)初始化流程
主要介紹JobSchedulerService服務(wù)的構(gòu)造函數(shù)的實(shí)現(xiàn)慎陵,
- 獲取系統(tǒng)服務(wù)(PackgeManager和ActivityManager);通過PM獲取uid喻奥,AM獲取是否異常應(yīng)用
- Jobhandler處理席纽;負(fù)責(zé)管理服務(wù)內(nèi)部的消息處理;主要分兩類撞蚕,Job任務(wù)狀態(tài)的消息處理(MSG_JOB_EXPIRED润梯, MSG_CHECK_JOB,MSG_STOP_JOB)甥厦,Job任務(wù)Active根據(jù)UID狀態(tài)更新(MSG_UID_ACTIVE更新Job任務(wù)Active為ture 纺铭,MSG_UID_IDLE和MSG_UID_GONE更新Job任務(wù)Active為false)
- Job常量數(shù)量和時(shí)間的初始化(前后臺(tái),idle矫渔,充電彤蔽,網(wǎng)絡(luò)連接, 電量,存儲(chǔ)庙洼,Standby, 失效時(shí)間) 以及settings數(shù)據(jù)庫與jobscheduler相關(guān)的數(shù)據(jù)變化的監(jiān)聽
- JobSchedulerStub的實(shí)現(xiàn)顿痪,繼承IJobScheduler.Stub的接口,用于與app進(jìn)行通訊(schedule函數(shù))
- JobConcurrencyManager的初始化油够, 該類是根據(jù)配置和系統(tǒng)狀態(tài)允許多少個(gè)Job任務(wù)共同運(yùn)行
dump里的配置信息如下:
Config={tot=10 bg min/max=2/6} Running[FG/BG (total)]: 0 / 0 (0) Pending: 0 / 0 (0) Actual max: 0 / 0 (0) Res BG: 0 Starting: 0 / 0 (0) Total: 0 / 0 (0)
- 創(chuàng)建應(yīng)用待機(jī)組的跟蹤 (app standby bucket tracker)
- 初始化各個(gè)子狀態(tài)控制模塊
- 注冊(cè)time change的receiver蚁袭,當(dāng)時(shí)間更新后重新計(jì)算Job任務(wù)的執(zhí)行時(shí)間
3.3 Job任務(wù)系統(tǒng)管理服務(wù)啟動(dòng)階段
Job任務(wù)系統(tǒng)管理服務(wù)的啟動(dòng)主要包含系統(tǒng)服務(wù)自身初始化和系統(tǒng)服務(wù)開始綁定到三方應(yīng)用兩個(gè)流程,
3.3.1 系統(tǒng)服務(wù)自身初始化完成 (PHASE_SYSTEM_SERVICES_READY)
- 初始化子條件狀態(tài)控制
for (StateController controller : mControllers) {
controller.onSystemServicesReady();
}
- 開始注冊(cè)broadcast receiver來監(jiān)聽package的相關(guān)變化(remove, change, restart, query package restart)
// Register br for package removals and user removals.
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
filter.addDataScheme("package");
getContext().registerReceiverAsUser(
mBroadcastReceiver, UserHandle.ALL, filter, null, null);
final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED);
getContext().registerReceiverAsUser(
mBroadcastReceiver, UserHandle.ALL, userFilter, null, null);
- 開始注冊(cè)broadcast receiver來監(jiān)聽uid的相關(guān)變化(gone, idle, active, procstate)
ActivityManager.getService().registerUidObserver(mUidObserver,
ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE
| ActivityManager.UID_OBSERVER_IDLE | ActivityManager.UID_OBSERVER_ACTIVE,
ActivityManager.PROCESS_STATE_UNKNOWN, null);
//JobConcurrencyManager的初始化
mConcurrencyManager.onSystemReady();
public void onSystemReady() {
mPowerManager = mContext.getSystemService(PowerManager.class);
final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
mContext.registerReceiver(mReceiver, filter);
onInteractiveStateChanged(mPowerManager.isInteractive());
}
- 取消當(dāng)前無效的Job任務(wù)
// Remove any jobs that are not associated with any of the current users.
cancelJobsForNonExistentUsers();
3.3.2 系統(tǒng)服務(wù)開始綁定到三方應(yīng)用 (PHASE_THIRD_PARTY_APPS_CAN_START)
- 獲取batterystats服務(wù)和DeviceIdleController
mReadyToRock = true;
mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
BatteryStats.SERVICE_NAME));
mLocalDeviceIdleController
= LocalServices.getService(DeviceIdleController.LocalService.class);
- 創(chuàng)建MAX_JOB_CONTEXTS_COUNT個(gè)JobServiceContext石咬,添加到mActiveServices JobServiceContext表達(dá)一個(gè)job的生命周期揩悄,每個(gè)job對(duì)應(yīng)該類的一個(gè)實(shí)例,該構(gòu)造中與JobPackageTracker和BatteryStats相關(guān)
// Create the "runners".
for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; i++) {
mActiveServices.add(
new JobServiceContext(this, mBatteryStats, mJobPackageTracker,
getContext().getMainLooper()));
}
- 把每個(gè)job任務(wù)在子條件狀態(tài)控制里做跟蹤
mJobs.forEachJob((job) -> {
for (int controller = 0; controller < mControllers.size(); controller++) {
final StateController sc = mControllers.get(controller);
sc.maybeStartTrackingJobLocked(job, null);
}
});
- 檢查job, 開啟job工作模式
mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
3.4 系統(tǒng)管理服務(wù)對(duì)Job任務(wù)的處理流程
JobSchedulerService是該模塊的主要實(shí)現(xiàn)類鬼悠,其工作流程為删性,
- JobScheduler將JobInfo實(shí)例(參數(shù)為Job ID和JobService的實(shí)例)注冊(cè)到JobSchedulerService服務(wù)中
- 由JobSchedulerService服務(wù)維護(hù)Job列表JobStore,JobStore中所存儲(chǔ)的Job會(huì)存入PendingJobs的列表里
- Job設(shè)置的條件被相應(yīng)的子StateController解讀并注冊(cè)
- 子StateController中的狀態(tài)被滿足時(shí)會(huì)把相應(yīng)的jobstatus中的滿足的限制條件設(shè)置為true焕窝, 并發(fā)送檢查job的消息給JobSchedulerService的
- 當(dāng)Job任務(wù)的條件全部滿足時(shí)把Job存入PendingJobs的以時(shí)間為序的隊(duì)列里JobConcurrencyManager觸發(fā)JobServiceContext去執(zhí)行相關(guān)的Job, 開啟Job生命周期的管理模塊
JobSchedulerService的Job任務(wù)執(zhí)行流程如下圖所示蹬挺,想要詳細(xì)了解的同學(xué)可根據(jù)代碼和如下流程自行查看。
4. Job任務(wù)條件狀態(tài)控制模塊
條件控制模塊是Job任務(wù)條件滿足的涌動(dòng)機(jī)它掂,主要作用是Job任務(wù)狀態(tài)的管理控制功能 巴帮,把調(diào)用者Job任務(wù)構(gòu)建滿足條件設(shè)置到相應(yīng)子狀態(tài)控制模塊(StateController的子類)中去,隨著Android版本的不斷升級(jí),該子模塊的功能不斷被擴(kuò)展添加榕茧。每個(gè)條件狀態(tài)控制會(huì)去接受系統(tǒng)的廣播信息垃沦,由此根據(jù)系統(tǒng)廣播狀態(tài)的變化信息來更新各個(gè)Job任務(wù)的滿足條件。
隨著系統(tǒng)版本的升級(jí)Job任務(wù)的狀態(tài)控制模塊在各個(gè)Android版本上演進(jìn)如下圖所示用押。
4.1 子條件狀態(tài)控制模塊(StateController的子類)
Job任務(wù)在初始化時(shí)肢簿,使用者對(duì)Job任務(wù)的條件設(shè)置通過條件位標(biāo)記的方法賦值給Job任務(wù)的請(qǐng)求條件變量(JobStatus的mRequiredConstraints),其設(shè)置條件會(huì)對(duì)應(yīng)設(shè)置到StateController的子類的條件狀態(tài)中只恨,Job任務(wù)主動(dòng)設(shè)置到狀態(tài)控制模塊里的條件稱為顯式滿足條件译仗,狀態(tài)控制模塊為Job任務(wù)添加的條件稱為隱式滿足條件。
該模塊的處理流程為官觅,子條件狀態(tài)控制模塊來監(jiān)控相關(guān)狀態(tài)(注冊(cè)BroadcastReceiver),狀態(tài)發(fā)生變更后會(huì)更新Job任務(wù)的滿足條件阐污;某個(gè)條件滿足會(huì)設(shè)置相應(yīng)的Job任務(wù)的滿足條件變量的某個(gè)條件標(biāo)記位為1(JobStatus的satisfiedConstraints變量的某指定條件位設(shè)置為1)休涤,當(dāng)一個(gè)Job任務(wù)所有的條件都滿足后(滿足條件為mReadyNotDozing && mReadyNotRestrictedInBg && (mReadyDeadlineSatisfied || mRequiredConstraintsOfInterest == satisfiedConstraints));最后由JobSchedulerService去觸發(fā)執(zhí)行Job任務(wù)笛辟。
4.1.1 顯式滿足條件的子狀態(tài)控制模塊
使用者主動(dòng)設(shè)置的條件稱為顯示滿足條件功氨,顯示滿足條件會(huì)主動(dòng)一一映射到各子條件狀態(tài)控制模塊,主要的顯示滿足相應(yīng)子條件控制模塊有手幢,
- 網(wǎng)絡(luò)連接狀態(tài)控制模塊捷凄,Job任務(wù)的網(wǎng)絡(luò)類型及連接條件由ConnectivityController來實(shí)現(xiàn),ConnectivityController來監(jiān)控網(wǎng)絡(luò)的連接情況围来。
- 執(zhí)行時(shí)間狀態(tài)控制模塊跺涤,針對(duì)Job任務(wù)的下次到期的時(shí)間設(shè)置alam提醒,該條件由TimeController實(shí)現(xiàn)监透。
- 系統(tǒng)閑時(shí)狀態(tài)控制模塊桶错,條件由IdleController來監(jiān)控系統(tǒng)閑時(shí)的進(jìn)入和退出,閑時(shí)定義為充電狀態(tài)下滅屏后71min胀蛮。
- 電池狀態(tài)控制模塊院刁,條件由BatteryController來實(shí)現(xiàn),其Job任務(wù)設(shè)置條件有正在充電和電池非低電情況粪狼。
- 存儲(chǔ)空間狀態(tài)控制模塊退腥,條件由StorageController來監(jiān)控存儲(chǔ)空間是否處于低位。
- 數(shù)據(jù)庫更新狀態(tài)控制模塊再榄,Contenet URI更新條件由ContentObserverController來實(shí)現(xiàn)狡刘,監(jiān)控Job任務(wù)設(shè)置的數(shù)據(jù)庫是否更新。
4.1.2 三個(gè)隱式滿足條件的子狀態(tài)控制模塊
有三個(gè)條件為系統(tǒng)自動(dòng)為Job任務(wù)強(qiáng)制添加不跟,使用者無法設(shè)置該類條件颓帝,其他條件均可被使用者設(shè)置,
該三個(gè)條件是:
- Doze限制執(zhí)行(DEVICE_NOT_DOZING),設(shè)備Doze狀態(tài)下不允許執(zhí)行Job任務(wù)购城,前臺(tái)和白名單應(yīng)用除外吕座,該條件被DeviceIdleJobsController子條件狀態(tài)控制。
- 后臺(tái)限制執(zhí)行(BACKGROUND_NOT_RESTRICTED)瘪板,根據(jù)AppStandby機(jī)制對(duì)后臺(tái)應(yīng)用的Job任務(wù)進(jìn)行限制吴趴,該條件被BackgroundJobsController子條件狀態(tài)控制。
- 應(yīng)用待機(jī)組(WITHIN_QUOTA)侮攀,應(yīng)用待機(jī)組條件控制锣枝,依照各待機(jī)組類別做相應(yīng)的限制,該條件被QuotaController子條件狀態(tài)控制兰英。四類應(yīng)用待機(jī)組對(duì)Job的有相關(guān)限制撇叁,活躍組無限制,工作級(jí)組在兩個(gè)小時(shí)允許執(zhí)行10分鐘畦贸,頻繁使用組八個(gè)小時(shí)允許執(zhí)行10分鐘陨闹,非常用組二十四小時(shí)允許執(zhí)行10分鐘。
4.2 條件狀態(tài)控制模塊屬性
條件狀態(tài)控制模塊屬性分為常駐屬性和可選屬性兩類薄坏,常駐屬性表明在該子條件狀態(tài)控制模塊必須實(shí)現(xiàn)這些屬性趋厉,該屬性是所有子條件狀態(tài)控制模塊共有的特性;可選屬性意思則為按需加載實(shí)現(xiàn)胶坠。
4.2.1. 常駐屬性
所有子狀態(tài)控制模塊都需要實(shí)現(xiàn)該屬性:
- 開啟任務(wù)狀態(tài)控制君账,每向JSS中加入一個(gè)Job,都會(huì)調(diào)用maybeStartTrackingJobLocked()方法開始記錄跟蹤此Job;
- 停止任務(wù)狀態(tài)控制沈善,當(dāng)Job任務(wù)執(zhí)行完成或被取消時(shí)乡数,都會(huì)調(diào)用maybeStopTrackingJobLocked()方法停止此Job的記錄。
4.2.2 可選屬性
子狀態(tài)控制模塊有選擇的實(shí)現(xiàn)該屬性:
- 重新調(diào)度失敗的任務(wù) rescheduleForFailureLocked (ContentObserverController)
- 常量或白名單的更新 onConstantsUpdatedLocked (ConnectivityController, QuotaController)
ConnectivityController: 在app idle里設(shè)置白名單為不允許
QuotaController:根據(jù)App的Bucket來更新任務(wù)的Quota狀態(tài)- 準(zhǔn)備可運(yùn)行的任務(wù) prepareForExecutionLocked (ContentObserverController, QuotaController)
ContentObserverController:為即將運(yùn)行的Job任務(wù)準(zhǔn)備好URI矮瘟。
QuotaController:將非TOP應(yīng)用添加到追蹤列表中瞳脓。- 應(yīng)用刪除后的清理 onUserRemovedLocked (ConnectivityController, QuotaController)
- 用戶刪除后的清理 onAppRemovedLocked (QuotaController)
- 評(píng)估任務(wù)狀態(tài) (ConnectivityController, TimerController)
ConnectivityController: 評(píng)估是否網(wǎng)絡(luò)連接的任務(wù)
TimerController: 評(píng)估最遲運(yùn)行(deadine)時(shí)間(latestRunTimeElapsedMillis)是否到期
5. Job任務(wù)生命周期控制模塊
5.1 Job任務(wù)生命周期介紹
Job任務(wù)的運(yùn)行流程Job任務(wù)的執(zhí)行狀態(tài)來表示的,可稱之為Job任務(wù)的生命周期處理澈侠,由狀態(tài)機(jī)來表現(xiàn)劫侧,JobServiceContext是該模塊的一個(gè)主要邏輯類,承擔(dān)Job任務(wù)的生命周期的處理和與使用者的Job任務(wù)執(zhí)行狀態(tài)同步的作用哨啃。
JobServiceContext實(shí)例與Job任務(wù)的生命周期為一一對(duì)應(yīng)烧栋,將JobServiceContext綁定到使用者的JobService上,綁定過程中開啟PowerManager.PARTIAL_WAKE_LOCK操作, Job任務(wù)完成后釋放該WAKE_LOCK拳球,其主要目的是通知使用者執(zhí)行Job任務(wù)的開啟執(zhí)行或停止等操作审姓,當(dāng)使用者被開啟任務(wù)的執(zhí)行時(shí),完成Job任務(wù)后會(huì)發(fā)起主動(dòng)通知到JobServiceContext祝峻。
每一個(gè)Job任務(wù)的初始狀態(tài)由完成(Finishing)狀態(tài)開始魔吐,一個(gè)成功運(yùn)行的Job任務(wù)執(zhí)行狀態(tài)轉(zhuǎn)換按綁定狀態(tài)(binding)->開啟狀態(tài)(starting)->執(zhí)行狀態(tài)(executing)->完成狀態(tài)(finishing)的流程來完成狀態(tài)的切換扎筒。
Job任務(wù)執(zhí)行狀態(tài)流程如下圖所示,綠色代表Job任務(wù)生命周期狀態(tài)處理流程酬姆,紫色代表與使用者Job任務(wù)執(zhí)行狀態(tài)傳遞及返回嗜桌,紅色代表Job任務(wù)停止?fàn)顟B(tài)處理流程。
5.2 超時(shí)機(jī)制處理機(jī)制
JobServiceContext擁有一個(gè)執(zhí)行狀態(tài)超時(shí)處理機(jī)制辞色,由于JobServiceContext與其目的是為了與使用者的調(diào)用建立一個(gè)容錯(cuò)能力骨宠,如果在約定時(shí)間內(nèi)未完成操作就會(huì)觸發(fā)超時(shí)狀態(tài)的切換及清理工作,各個(gè)執(zhí)行狀態(tài)的超時(shí)時(shí)間設(shè)置為綁定狀態(tài)超時(shí)18s相满,開啟狀態(tài)超時(shí)8s层亿,執(zhí)行狀態(tài)超時(shí)600s;當(dāng)綁定和開啟狀態(tài)超時(shí)被觸發(fā)后執(zhí)行狀態(tài)切換到完成狀態(tài)立美,去運(yùn)行Job任務(wù)的清除動(dòng)作匿又。
5.3 停止?fàn)顟B(tài)的處理機(jī)制
當(dāng)在執(zhí)行狀態(tài)下觸發(fā)超時(shí),切換到停止?fàn)顟B(tài)悯辙,調(diào)用使用者的停止函數(shù)琳省,執(zhí)行停止成功后再把狀態(tài)切換到完成狀態(tài)。使用者中的JobServiceEngine由三個(gè)消息(MSG_EXECUTE_JOB, MSG_STOP_JOB, MSG_JOB_FINISHED)來構(gòu)建執(zhí)行流程躲撰, 其中執(zhí)行和停止操作由JobServiceContext主動(dòng)觸發(fā),而完成操作是被動(dòng)觸發(fā)JobServiceContext击费。
5.4 狀態(tài)取消處理機(jī)制
執(zhí)行狀態(tài)失敗處理與超時(shí)機(jī)制的處理邏輯是一致的拢蛋,一旦觸發(fā)取消操作,綁定和開啟狀態(tài)切換到完成狀態(tài)做后續(xù)的清理工作蔫巩;而執(zhí)行狀態(tài)下的取消操作谆棱,會(huì)切換到停止?fàn)顟B(tài),調(diào)用使用者的停止函數(shù)圆仔,執(zhí)行停止成功后再把狀態(tài)切換到完成狀態(tài)垃瞧。
5.5 Job任務(wù)的清除
完成狀態(tài)(Finishing)后的統(tǒng)一清除。設(shè)置狀態(tài)為完成狀態(tài)坪郭,解除使用者的JobService綁定个从,由系統(tǒng)統(tǒng)一清理未綁定的服務(wù);并通知JobSchedulerService該Job已完成歪沃,停止繼續(xù)檢測該Job管理狀態(tài)嗦锐。
5.6 設(shè)計(jì)要點(diǎn)
- JobServiceContext實(shí)現(xiàn)與使用者通訊不返回的timeout容錯(cuò)機(jī)制**
- 執(zhí)行狀態(tài)同步到使用者分為主動(dòng)狀態(tài)更新和被動(dòng)狀態(tài)更新兩類,除完成狀態(tài)更新為被動(dòng)狀態(tài)以外其他狀態(tài)皆為JobServiceContext主動(dòng)設(shè)置**
- 執(zhí)行狀態(tài)的最后結(jié)束狀態(tài)皆為完成狀態(tài)沪曙,統(tǒng)一完成任務(wù)的清除操作**
作者:林芊_lqsohu
鏈接:http://www.reibang.com/p/e1b4d952c79f
來源:簡書
著作權(quán)歸作者所有奕污。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處液走。