-
概述
WorkManager是什么萎胰?
WorkManager是適合用于持久性工作的推薦解決方案钝尸。如果工作始終要通過(guò)應(yīng)用重啟和系統(tǒng)重新啟動(dòng)來(lái)調(diào)度作烟,便是持久性的工作。由于大多數(shù)后臺(tái)處理操作都是通過(guò)持久性工作完成的球涛,因此 WorkManager 是適用于后臺(tái)處理操作的主要推薦 API。
WorkManager 可處理三種類型的持久性工作:
- 立即執(zhí)行:必須立即開始且很快就完成的任務(wù)校镐,可以加急宾符。
- 長(zhǎng)時(shí)間運(yùn)行:運(yùn)行時(shí)間可能較長(zhǎng)(有可能超過(guò) 10 分鐘)的任務(wù)。
- 可延期執(zhí)行:延期開始并且可以定期運(yùn)行的預(yù)定任務(wù)灭翔。
除此之外,WorkManager還可添加很多額外功能:
使用工作約束明確定義工作運(yùn)行的最佳條件辣苏。例如肝箱,僅在設(shè)備采用不按流量計(jì)費(fèi)的網(wǎng)絡(luò)連接時(shí)、當(dāng)設(shè)備處于空閑狀態(tài)或者有足夠的電量時(shí)運(yùn)行稀蟋。
-
WorkManager 允許您使用靈活的調(diào)度窗口調(diào)度工作煌张,以運(yùn)行一次性或重復(fù)工作。您還可以對(duì)工作進(jìn)行標(biāo)記或命名退客,以便調(diào)度唯一的骏融、可替換的工作以及監(jiān)控或取消工作組。
已調(diào)度的工作存儲(chǔ)在內(nèi)部托管的 SQLite 數(shù)據(jù)庫(kù)中萌狂,由 WorkManager 負(fù)責(zé)確保該工作持續(xù)進(jìn)行档玻,并在設(shè)備重新啟動(dòng)后重新調(diào)度。
此外茫藏,WorkManager 遵循低電耗模式等省電功能和最佳做法误趴,因此您在這方面無(wú)需擔(dān)心。
您可以使用 WorkManager 調(diào)度需在后臺(tái)立即執(zhí)行的工作务傲。您應(yīng)該使用加急工作來(lái)處理對(duì)用戶來(lái)說(shuō)很重要且會(huì)在幾分鐘內(nèi)完成的任務(wù)凉当。
有時(shí)工作會(huì)失敗。WorkManager 提供了靈活的重試政策售葡,包括可配置的指數(shù)退避政策看杭。
對(duì)于復(fù)雜的相關(guān)工作,您可以使用直觀的接口將各個(gè)工作任務(wù)串聯(lián)起來(lái)挟伙,這樣您便可以控制哪些部分依序運(yùn)行楼雹,哪些部分并行運(yùn)行。對(duì)于每項(xiàng)工作任務(wù)尖阔,您可以定義工作的輸入和輸出數(shù)據(jù)烘豹。將工作串聯(lián)在一起時(shí),WorkManager 會(huì)自動(dòng)將輸出數(shù)據(jù)從一個(gè)工作任務(wù)傳遞給下一個(gè)工作任務(wù)诺祸。
WorkManager 無(wú)縫集成 Coroutines 和 RxJava携悯,讓您可以插入自己的異步 API,非常靈活筷笨。
WorkManager 適用于需要可靠運(yùn)行的工作憔鬼,即使用戶導(dǎo)航離開屏幕龟劲、退出應(yīng)用或重啟設(shè)備也不影響工作的執(zhí)行。例如:
- 向后端服務(wù)發(fā)送日志或分析數(shù)據(jù)轴或。
- 定期將應(yīng)用數(shù)據(jù)與服務(wù)器同步昌跌。
WorkManager 不適用于那些可在應(yīng)用進(jìn)程結(jié)束時(shí)安全終止的進(jìn)程內(nèi)后臺(tái)工作。它也并非對(duì)所有需要立即執(zhí)行的工作都適用的通用解決方案照雁,對(duì)于對(duì)于短暫的蚕愤、應(yīng)用存活周期內(nèi)的可以使用協(xié)程、RxJava饺蚊、線程池等來(lái)處理萍诱;而對(duì)于精確的、在低電耗模式下也能被喚醒的任務(wù)污呼,則使用AlarmManager(在電源和資源管理方面并不高效裕坊,但是貴在精確)來(lái)完成,適合用于精確鬧鐘或通知(例如日歷活動(dòng))場(chǎng)景燕酷,不適合后臺(tái)工作籍凝。
-
使用入門
-
添加依賴
dependencies { def work_version = "2.8.0" // (Java only) implementation "androidx.work:work-runtime:$work_version" // Kotlin + coroutines implementation "androidx.work:work-runtime-ktx:$work_version" // optional - RxJava2 support implementation "androidx.work:work-rxjava2:$work_version" // optional - GCMNetworkManager support implementation "androidx.work:work-gcm:$work_version" // optional - Test helpers androidTestImplementation "androidx.work:work-testing:$work_version" // optional - Multiprocess support implementation "androidx.work:work-multiprocess:$work_version" }
-
創(chuàng)建Worker
class UploadWorker(appContext: Context, workerParams: WorkerParameters): Worker(appContext, workerParams) { override fun doWork(): Result { // Do the work here--in this case, upload the images. uploadImages() /**結(jié)果返回*/ //Result.failure() //Result.retry() return Result.success( Data.Builder() .putString("name","MPH") .build() ) } }
-
創(chuàng)建request并開啟后臺(tái)任務(wù)
val uploadWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<UploadWorker>().build() //啟動(dòng)任務(wù) WorkManager.getInstance(myContext).enqueue(uploadWorkRequest)
-
-
任務(wù)配置
上面的使用入門介紹了使用WorkManager的一般步驟,下面我們來(lái)看看如何根據(jù)不同需求做具體的任務(wù)配置苗缩。
WorkRequest
本身是抽象基類饵蒂。該類有兩個(gè)派生實(shí)現(xiàn),可用于創(chuàng)建OneTimeWorkRequest
和PeriodicWorkRequest
請(qǐng)求酱讶。顧名思義苹享,OneTimeWorkRequest
適用于調(diào)度非重復(fù)性工作,而PeriodicWorkRequest
則更適合調(diào)度以一定間隔重復(fù)執(zhí)行的工作浴麻。-
一次性工作
OneTimeWorkRequest
創(chuàng)建對(duì)于無(wú)需額外配置的簡(jiǎn)單工作得问,可以使用靜態(tài)方法
from
:val myWorkRequest = OneTimeWorkRequest.from(MyWork::class.java)
對(duì)于更復(fù)雜的工作,可以使用構(gòu)建器:
val uploadWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<MyWork>() // Additional configuration .build()
-
定期任務(wù)
PeriodicWorkRequest
創(chuàng)建有時(shí)可能需要定期運(yùn)行某些工作软免。例如宫纬,可能要定期備份數(shù)據(jù)、定期下載應(yīng)用中的新鮮內(nèi)容或者定期上傳日志到服務(wù)器膏萧。
//內(nèi)聯(lián)方法簡(jiǎn)化創(chuàng)建方式(內(nèi)部也是用PeriodicWorkRequest.Builder) val saveRequest = PeriodicWorkRequestBuilder<SaveImageToFileWorker>(1, TimeUnit.HOURS) // 間隔一小時(shí) .build() //手動(dòng)創(chuàng)建 PeriodicWorkRequest.Builder(NewsWork::class.java, 20, TimeUnit.MINUTES).build()
時(shí)間間隔定義為兩次重復(fù)執(zhí)行之間的最短時(shí)間漓骚,實(shí)際上任務(wù)執(zhí)行時(shí)機(jī)并不是嚴(yán)格按照間隔時(shí)間安排,但是一定會(huì)超過(guò)最短間隔時(shí)間榛泛。工作器的確切執(zhí)行時(shí)間取決于您在 WorkRequest 對(duì)象中設(shè)置的約束以及系統(tǒng)執(zhí)行的優(yōu)化:
val myUploadWork = PeriodicWorkRequestBuilder<SaveImageToFileWorker>( 1, TimeUnit.HOURS, // repeatInterval (the period cycle) 15, TimeUnit.MINUTES) // flexInterval .build()
任務(wù)會(huì)在從
repeatInterval - flexInterval
開始蝌蹂,一直到間隔結(jié)束的這段時(shí)間內(nèi)運(yùn)行。任務(wù)間隔時(shí)間和分給任務(wù)的執(zhí)行時(shí)間段都有最小限制:
/** * The minimum interval duration for {@link PeriodicWorkRequest} (in milliseconds). */ public static final long MIN_PERIODIC_INTERVAL_MILLIS = 15 * 60 * 1000L; // 15 minutes. /** * The minimum flex duration for {@link PeriodicWorkRequest} (in milliseconds). */ public static final long MIN_PERIODIC_FLEX_MILLIS = 5 * 60 * 1000L; // 5 minutes.
-
加急工作
加急工作具有以下特征:
- 重要性:加急工作適用于對(duì)用戶很重要或由用戶啟動(dòng)的任務(wù)曹锨。
- 速度:加急工作最適合那些立即啟動(dòng)并在幾分鐘內(nèi)完成的簡(jiǎn)短任務(wù)孤个。
- 配額:限制前臺(tái)執(zhí)行時(shí)間的系統(tǒng)級(jí)配額決定了加急作業(yè)是否可以啟動(dòng)。
- 電源管理:電源管理限制(如省電模式和低電耗模式)不太可能影響加急工作沛简。
- 延遲時(shí)間:系統(tǒng)立即執(zhí)行加急工作齐鲤,前提是系統(tǒng)的當(dāng)前工作負(fù)載允許執(zhí)行此操作斥废。這意味著這些工作對(duì)延遲時(shí)間較為敏感,不能安排到以后執(zhí)行给郊。
在用戶想要發(fā)送消息或附加的圖片時(shí)牡肉,可能會(huì)在聊天應(yīng)用內(nèi)使用加急工作。同樣淆九,處理付款或訂閱流程的應(yīng)用也可能需要使用加急工作统锤。這是因?yàn)檫@些任務(wù)對(duì)用戶很重要,會(huì)在后臺(tái)快速執(zhí)行炭庙,并需要立即開始執(zhí)行饲窿。
執(zhí)行時(shí)間并非無(wú)限制,而是受配額限制煤搜。如果您的應(yīng)用使用其執(zhí)行時(shí)間并達(dá)到分配的配額,在配額刷新之前唧席,您無(wú)法再執(zhí)行加急工作擦盾。這樣,Android 可以更有效地在應(yīng)用之間平衡資源淌哟。
每個(gè)應(yīng)用均有自己的前臺(tái)執(zhí)行時(shí)間配額迹卢。可用的執(zhí)行時(shí)間取決于待機(jī)模式存儲(chǔ)分區(qū)和進(jìn)程的重要性徒仓。
調(diào)用
setExpedited()
來(lái)聲明WorkRequest
應(yīng)該使用加急作業(yè)腐碱,以盡可能快的速度運(yùn)行:val request = OneTimeWorkRequestBuilder() .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) .build() WorkManager.getInstance(context) .enqueue(request)
參數(shù)表示配額策略,有兩種:
-
OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST
掉弛,這會(huì)導(dǎo)致作業(yè)作為普通工作請(qǐng)求運(yùn)行症见。 -
OutOfQuotaPolicy.DROP_WORK_REQUEST
,這會(huì)在配額不足時(shí)導(dǎo)致請(qǐng)求取消殃饿。
在系統(tǒng)負(fù)載過(guò)高或者配額滿了的情況下加急任務(wù)也會(huì)被延遲谋作。
-
工作約束
可以對(duì)定期工作設(shè)置約束。例如乎芳,你可以為工作請(qǐng)求添加約束遵蚜,以便工作僅在用戶設(shè)備充電時(shí)運(yùn)行。在這種情況下奈惑,除非滿足約束條件吭净,否則即使過(guò)了定義的重復(fù)間隔,
PeriodicWorkRequest
也不會(huì)運(yùn)行肴甸。這可能會(huì)導(dǎo)致工作在某次運(yùn)行時(shí)出現(xiàn)延遲寂殉,甚至?xí)蛟谙鄳?yīng)間隔內(nèi)未滿足條件而被跳過(guò)。例如原在,以下代碼會(huì)構(gòu)建了一個(gè)工作請(qǐng)求不撑,該工作請(qǐng)求僅在用戶設(shè)備正在充電且連接到 Wi-Fi 網(wǎng)絡(luò)時(shí)才會(huì)運(yùn)行:
val constraints = Constraints.Builder() .setRequiredNetworkType(NetworkType.UNMETERED) .setRequiresCharging(true) .build() val myWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<MyWork>() .setConstraints(constraints) .build()
如果指定了多個(gè)約束文兢,工作將僅在滿足所有約束時(shí)才會(huì)運(yùn)行。
如果在工作運(yùn)行時(shí)不再滿足某個(gè)約束焕檬,WorkManager 將停止工作器姆坚。系統(tǒng)將在滿足所有約束后重試工作。
-
延遲執(zhí)行
如果工作沒有約束实愚,或者當(dāng)工作加入隊(duì)列時(shí)所有約束都得到了滿足兼呵,那么系統(tǒng)可能會(huì)選擇立即運(yùn)行該工作。如果您不希望工作立即運(yùn)行腊敲,可以將工作指定為在經(jīng)過(guò)一段最短初始延遲時(shí)間后再啟動(dòng)击喂。
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>() //10分鐘后執(zhí)行 .setInitialDelay(10, TimeUnit.MINUTES) .build()
-
重試策略
如果需要讓 WorkManager 重試工作,可以從doWork方法返回
Result.retry()
碰辅。然后懂昂,系統(tǒng)將根據(jù)退避延遲時(shí)間和退避政策重新調(diào)度工作。- 退避延遲時(shí)間指定了首次嘗試后重試工作前的最短等待時(shí)間没宾。此值建議不超過(guò) 10 秒~5小時(shí)范圍凌彬。
- 退避政策定義了在后續(xù)重試過(guò)程中,退避延遲時(shí)間隨時(shí)間以怎樣的方式增長(zhǎng)循衰。WorkManager 支持 2 個(gè)退避政策铲敛,即
LINEAR
和EXPONENTIAL
。
每個(gè)工作請(qǐng)求都有退避政策和退避延遲時(shí)間会钝。默認(rèn)政策是
EXPONENTIAL
伐蒋,延遲時(shí)間為 10 秒,但您可以在工作請(qǐng)求配置中替換此設(shè)置迁酸。如果政策為LINEAR
先鱼,每次嘗試重試時(shí),重試間隔都會(huì)增加約 10 秒奸鬓。例如型型,第一次運(yùn)行以Result.retry()
結(jié)束并在 10 秒后重試;然后全蝶,如果工作在后續(xù)嘗試后繼續(xù)返回Result.retry()
闹蒜,那么接下來(lái)會(huì)在 20 秒、30 秒抑淫、40 秒后重試绷落,以此類推。如果退避政策設(shè)置為EXPONENTIAL
始苇,那么重試時(shí)長(zhǎng)序列將接近 20砌烁、40、80 秒,以此類推函喉。val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>() .setBackoffCriteria( BackoffPolicy.LINEAR, OneTimeWorkRequest.MIN_BACKOFF_MILLIS,//可以指定自定義時(shí)長(zhǎng) TimeUnit.MILLISECONDS) .build()
-
輸入數(shù)據(jù)和輸出數(shù)據(jù)
// Define the Worker requiring input class UploadWork(appContext: Context, workerParams: WorkerParameters) : Worker(appContext, workerParams) { override fun doWork(): Result { val imageUriInput = inputData.getString("IMAGE_URI") ?: return Result.failure() uploadFile(imageUriInput) //若Worker 停止后避归,從 Worker.doWork() 返回什么已不重要;Result 將被忽略 return Result.success( //設(shè)置輸出數(shù)據(jù) Data.Builder() .putString("name","MPH") .build() ) } ... } val myUploadWork = OneTimeWorkRequestBuilder<UploadWork>() //設(shè)置輸入數(shù)據(jù) .setInputData(workDataOf( "IMAGE_URI" to "http://..." )) .build()
輸入輸出數(shù)據(jù)都是Map形式的Data類型管呵。
-
設(shè)置Tag
每個(gè)工作請(qǐng)求都可以添加多個(gè)標(biāo)識(shí)符梳毙,該標(biāo)識(shí)符可用于在以后標(biāo)識(shí)該工作,以便取消工作或觀察其進(jìn)度捐下。
如果有一組在邏輯上相關(guān)的工作账锹,對(duì)這些工作項(xiàng)進(jìn)行標(biāo)記可能也會(huì)很有幫助。通過(guò)標(biāo)記坷襟,您一起處理一組工作請(qǐng)求奸柬。
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>() .addTag("cleanup") .addTag("room") //可以添加多個(gè),相當(dāng)于添加分類 .build()
-
-
管理任務(wù)
-
設(shè)置唯一工作
在將工作加入隊(duì)列時(shí)請(qǐng)小心謹(jǐn)慎婴程,以避免重復(fù)廓奕。例如,應(yīng)用可能會(huì)每 24 小時(shí)嘗試將其日志上傳到后端服務(wù)档叔。如果不謹(jǐn)慎桌粉,即使作業(yè)只需運(yùn)行一次,最終也可能會(huì)多次將同一作業(yè)加入隊(duì)列蹲蒲。為了實(shí)現(xiàn)此目標(biāo)番甩,您可以將工作調(diào)度為唯一工作侵贵。
唯一工作既可用于一次性工作届搁,也可用于定期工作:
-
WorkManager.enqueueUniqueWork()
(用于一次性工作) -
WorkManager.enqueueUniquePeriodicWork()
(用于定期工作)
這兩種方法都接受 3 個(gè)參數(shù):
- uniqueWorkName - 用于唯一標(biāo)識(shí)工作請(qǐng)求的
String
。 - existingWorkPolicy - 此
enum
可告知 WorkManager:如果已有使用該名稱且尚未完成的唯一工作鏈窍育,應(yīng)執(zhí)行什么操作卡睦。 - work - 要調(diào)度的
WorkRequest
。
val sendLogsWorkRequest = PeriodicWorkRequestBuilder<SendLogsWorker>(24, TimeUnit.HOURS) .setConstraints(Constraints.Builder() .setRequiresCharging(true) .build() ) .build() WorkManager.getInstance(this).enqueueUniquePeriodicWork( "sendLogs", //自定義名字 ExistingPeriodicWorkPolicy.KEEP, sendLogsWorkRequest )
第二個(gè)參數(shù)是當(dāng)設(shè)置多個(gè)同一名字的唯一任務(wù)時(shí)如何處理這種沖突漱抓。
對(duì)于一次性工作表锻,您需要提供一個(gè)
ExistingWorkPolicy
,支持用于處理沖突的 4 個(gè)選項(xiàng)如下:REPLACE
:用新工作替換現(xiàn)有工作乞娄。此選項(xiàng)將取消現(xiàn)有工作瞬逊。KEEP
:保留現(xiàn)有工作,并忽略新工作仪或。APPEND
:將新工作附加到現(xiàn)有工作的末尾确镊。此政策將導(dǎo)致您的新工作鏈接到現(xiàn)有工作,在現(xiàn)有工作完成后運(yùn)行》渡荆現(xiàn)有工作將成為新工作的先決條件蕾域。如果現(xiàn)有工作變?yōu)?CANCELLED
或FAILED
狀態(tài),新工作也會(huì)變?yōu)?CANCELLED
或FAILED
。如果您希望無(wú)論現(xiàn)有工作的狀態(tài)如何都運(yùn)行新工作旨巷,請(qǐng)改用APPEND_OR_REPLACE
巨缘。APPEND_OR_REPLACE
函數(shù)類似于APPEND
,不過(guò)它并不依賴于先決條件工作狀態(tài)采呐。即使現(xiàn)有工作變?yōu)?CANCELLED
或FAILED
狀態(tài)若锁,新工作仍會(huì)運(yùn)行。
而對(duì)于定期工作懈万,需要提供一個(gè)
ExistingPeriodicWorkPolicy
拴清,它支持REPLACE
和KEEP
這兩個(gè)選項(xiàng)。這些選項(xiàng)的功能與其對(duì)應(yīng)的 ExistingWorkPolicy 功能相同会通。 -
-
監(jiān)聽任務(wù)進(jìn)度和結(jié)果
//獲取 workManager.getWorkInfoById(syncWorker.id) // ListenableFuture<WorkInfo> workManager.getWorkInfosForUniqueWork("sync") // ListenableFuture<List<WorkInfo>> workManager.getWorkInfosByTag("syncTag") // ListenableFuture<List<WorkInfo>> val work1Id = getWorkInfoById(work1.id).get().id getWorkInfosByTag("cleanup").get().forEach { val workState = it.state val workOutputData = it.outputData } //取消 workManager.cancelWorkById(syncWorker.id) workManager.cancelUniqueWork("sync") workManager.cancelAllWorkByTag("syncTag")
workManager.getWorkInfoByIdLiveData(syncWorker.id) .observe(viewLifecycleOwner) { workInfo -> if(workInfo?.state == WorkInfo.State.SUCCEEDED) { Snackbar.make(requireView(), R.string.work_completed, Snackbar.LENGTH_SHORT) .show() } }
WorkManager 2.4.0 及更高版本支持使用
WorkQuery
對(duì)象對(duì)已加入隊(duì)列的作業(yè)進(jìn)行復(fù)雜查詢口予。WorkQuery 支持按工作的標(biāo)記、狀態(tài)和唯一工作名稱的組合進(jìn)行查詢:val workQuery = WorkQuery.Builder .fromTags(listOf("syncTag")) .addStates(listOf(WorkInfo.State.FAILED, WorkInfo.State.CANCELLED)) .addUniqueWorkNames(listOf("preProcess", "sync") ) .build() val workInfos: ListenableFuture<List<WorkInfo>> = workManager.getWorkInfos(workQuery)
WorkManager 會(huì)在后臺(tái)檢查工作的
State
涕侈。如果工作已經(jīng)完成沪停,系統(tǒng)不會(huì)執(zhí)行任何操作。否則裳涛,工作的狀態(tài)會(huì)更改為CANCELLED
木张,之后就不會(huì)運(yùn)行這個(gè)工作。任何依賴于此工作的WorkRequest
作業(yè)也將變?yōu)?CANCELLED
端三∠侠瘢可以重寫ListenableWorker.onStopped()
方法來(lái)處理清理工作,它會(huì)在停止時(shí)調(diào)用郊闯,可以調(diào)用ListenableWorker.isStopped()
方法以檢查工作器是否已停止妻献。對(duì)于使用
ListenableWorker
或Worker
的 Java 開發(fā)者,setProgressAsync()
API 會(huì)返回ListenableFuture<Void>
团赁;更新進(jìn)度是異步過(guò)程育拨,因?yàn)楦逻^(guò)程涉及將進(jìn)度信息存儲(chǔ)在數(shù)據(jù)庫(kù)中。在 Kotlin 中欢摄,可以使用CoroutineWorker
對(duì)象的setProgress()
擴(kuò)展函數(shù)來(lái)更新進(jìn)度信息:import android.content.Context import androidx.work.CoroutineWorker import androidx.work.Data import androidx.work.WorkerParameters import kotlinx.coroutines.delay class ProgressWorker(context: Context, parameters: WorkerParameters) : CoroutineWorker(context, parameters) { companion object { const val Progress = "Progress" private const val delayDuration = 1L } override suspend fun doWork(): Result { val firstUpdate = workDataOf(Progress to 0) val lastUpdate = workDataOf(Progress to 100) //如果是Worker熬丧,則調(diào)用setProgressAsync方法 setProgress(firstUpdate) delay(delayDuration) setProgress(lastUpdate) return Result.success() } }
觀察進(jìn)度信息也很簡(jiǎn)單,可以使用
getWorkInfoBy…()
或getWorkInfoBy…LiveData()
方法怀挠,并引用WorkInfo
:WorkManager.getInstance(applicationContext) // requestId is the WorkRequest id .getWorkInfoByIdLiveData(requestId) .observe(observer, Observer { workInfo: WorkInfo? -> if (workInfo != null) { val progress = workInfo.progress val value = progress.getInt(Progress, 0) // Do something with progress information } })
-
鏈接任務(wù)
鏈接任務(wù)只能用于OneTimeWorkRequest析蝴。
如需創(chuàng)建工作鏈,您可以使用
WorkManager.beginWith(OneTimeWorkRequest)
或WorkManager.beginWith(List)
绿淋,這會(huì)返回WorkContinuation
實(shí)例闷畸。然后,可以使用
WorkContinuation
通過(guò)then(OneTimeWorkRequest)
或then(List)
添加OneTimeWorkRequest
依賴實(shí)例躬它。 .每次調(diào)用
WorkContinuation.then(...)
都會(huì)返回一個(gè)新的WorkContinuation
實(shí)例边坤。如果添加了OneTimeWorkRequest
實(shí)例的List
竣稽,這些請(qǐng)求可能會(huì)并行運(yùn)行错忱。最后,您可以使用
WorkContinuation.enqueue()
方法對(duì)WorkContinuation
工作鏈執(zhí)行enqueue()
操作疮跑。WorkManager.getInstance(myContext) // Candidates to run in parallel .beginWith(listOf(plantName1, plantName2, plantName3)) // Dependent work (only runs after all previous work in chain) .then(cache) .then(upload) // Call enqueue to kick things off .enqueue()
當(dāng)您鏈接
OneTimeWorkRequest
實(shí)例時(shí),父級(jí)工作請(qǐng)求的輸出將作為子級(jí)的輸入傳入凸舵。因此祖娘,在上面的示例中,plantName1
啊奄、plantName2
和plantName3
的輸出將作為cache
請(qǐng)求的輸入傳入渐苏。為了管理來(lái)自多個(gè)父級(jí)工作請(qǐng)求的輸入,WorkManager 使用
InputMerger
菇夸。WorkManager 提供兩種不同類型的
InputMerger
:-
OverwritingInputMerger
會(huì)嘗試將所有輸入中的所有鍵添加到輸出中琼富。如果發(fā)生沖突,它會(huì)覆蓋先前設(shè)置的鍵庄新。是默認(rèn)的合并規(guī)則鞠眉。 -
ArrayCreatingInputMerger
會(huì)嘗試合并輸入,并在必要時(shí)創(chuàng)建數(shù)組择诈。val cache: OneTimeWorkRequest = OneTimeWorkRequestBuilder<PlantWorker>() .setInputMerger(ArrayCreatingInputMerger::class) .setConstraints(constraints) .build()
如果有更具體的用例械蹋,則可以創(chuàng)建
InputMerger
的子類來(lái)編寫自己的用例。當(dāng)上游的任務(wù)成功后才會(huì)執(zhí)行下游的任務(wù)羞芍,只要上游的任務(wù)失敗或者取消哗戈,則其下游的任務(wù)都會(huì)失敗或者取消,但是對(duì)同級(jí)的任務(wù)不會(huì)被影響荷科。
-
-
-
WorkManager配置和初始化
從WorkManager2.6開始唯咬,在androidx.work:work-runtime庫(kù)中的AndroidManifest文件中就配置了WorkManagerInitializer的provider:
<application> <provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" android:exported="false" tools:node="merge" > <meta-data android:name="androidx.work.WorkManagerInitializer" android:value="androidx.startup" /> </provider> ... </application>
public final class WorkManagerInitializer implements Initializer<WorkManager> { @Override public WorkManager create(@NonNull Context context) { WorkManager.initialize(context, new Configuration.Builder().build()); return WorkManager.getInstance(context); } ... }
這就說(shuō)明,如果你使用的是2.6以上版本的話步做,在應(yīng)用啟動(dòng)時(shí)副渴,WorkManager就會(huì)自動(dòng)初始化奈附。那如果我們想要在使用時(shí)才初始化的話怎么辦呢全度?這時(shí)就得根據(jù)Manifest合并規(guī)則在app的AndroidManifest中重寫來(lái)覆蓋它:
<!-- 如果應(yīng)用不需要InitializationProvider的話可以直接移除InitializationProvider --> <provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" tools:node="remove"> </provider> <!--如果還用到其他Initializer,只是禁用WorkManagerInitializer的話--> <provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" android:exported="false" tools:node="merge"> <meta-data android:name="androidx.work.WorkManagerInitializer" android:value="androidx.startup" tools:node="remove" /> </provider>
如果使用2.6之前的版本斥滤,則為:
<provider android:name="androidx.work.impl.WorkManagerInitializer" android:authorities="${applicationId}.workmanager-init" tools:node="remove" />
如果想要自定義WorkManager配置将鸵,則需要讓
Application
類實(shí)現(xiàn)Configuration.Provider
接口,并提供自己的Configuration.Provider.getWorkManagerConfiguration
() 實(shí)現(xiàn)佑颇。當(dāng)需要使用 WorkManager 時(shí)顶掉,請(qǐng)務(wù)必調(diào)用方法WorkManager.getInstance(Context)
。WorkManager 會(huì)調(diào)用應(yīng)用的自定義getWorkManagerConfiguration()
方法來(lái)發(fā)現(xiàn)其Configuration
(無(wú)需自行調(diào)用WorkManager.initialize()
):class MyApplication() : Application(), Configuration.Provider { override fun getWorkManagerConfiguration() = Configuration.Builder() .setMinimumLoggingLevel(android.util.Log.INFO) .setExecutor(Executors.newFixedThreadPool(8)) .build() }
Jetpack之WorkManager
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
- 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)啡浊,“玉大人觅够,你說(shuō)我怎么就攤上這事∠锵” “怎么了喘先?”我有些...
- 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)廷粒。 經(jīng)常有香客問我苹祟,道長(zhǎng),這世上最難降的妖魔是什么评雌? 我笑而不...
- 正文 為了忘掉前任树枫,我火速辦了婚禮,結(jié)果婚禮上景东,老公的妹妹穿的比我還像新娘砂轻。我一直安慰自己,他們只是感情好斤吐,可當(dāng)我...
- 文/花漫 我一把揭開白布搔涝。 她就那樣靜靜地躺著,像睡著了一般和措。 火紅的嫁衣襯著肌膚如雪庄呈。 梳的紋絲不亂的頭發(fā)上,一...
- 那天派阱,我揣著相機(jī)與錄音诬留,去河邊找鬼。 笑死贫母,一個(gè)胖子當(dāng)著我的面吹牛文兑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播腺劣,決...
- 文/蒼蘭香墨 我猛地睜開眼绿贞,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了橘原?” 一聲冷哼從身側(cè)響起籍铁,我...
- 序言:老撾萬(wàn)榮一對(duì)情侶失蹤涡上,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后拒名,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吓懈,經(jīng)...
- 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
- 正文 我和宋清朗相戀三年靡狞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了耻警。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
- 正文 年R本政府宣布,位于F島的核電站武契,受9級(jí)特大地震影響募判,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜咒唆,卻給世界環(huán)境...
- 文/蒙蒙 一届垫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧全释,春花似錦装处、人聲如沸。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至李命,卻和暖如春登淘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背封字。 一陣腳步聲響...
- 正文 我出身青樓辩撑,卻偏偏與公主長(zhǎng)得像界斜,于是被迫代替她去往敵國(guó)和親仿耽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
推薦閱讀更多精彩內(nèi)容
- 簡(jiǎn)介 WorkManager 主要的能力: 可輕松調(diào)度那些即使在退出應(yīng)用或重啟設(shè)備后仍然可以運(yùn)行的可延期的異步任務(wù)...
- WorkManager是干啥的各薇。 WorkManager is the recommended library f...
- WorkManager WorkManager是Google最新的后臺(tái)任務(wù)調(diào)度解決方案,Google計(jì)劃2020年...
- 一项贺、WorkManager 特點(diǎn)及適用場(chǎng)景 特點(diǎn) 保證任務(wù)一定會(huì)被執(zhí)行WorkManager 有自己的數(shù)據(jù)庫(kù)君躺,每一...
- 1.特點(diǎn) 1.立即執(zhí)行:必須立即開始且很快就完成的任務(wù),可以加急开缎。2.長(zhǎng)時(shí)間運(yùn)行:運(yùn)行時(shí)間可能較長(zhǎng)(有可能超過(guò) 1...