Android?WorkManager的概念和使用詳細(xì)指南
1. WorkManager基礎(chǔ)與核心概念
1.1 WorkManager概述
WorkManager是Android Jetpack架構(gòu)組件庫(kù)的核心成員,專(zhuān)為管理可靠的后臺(tái)任務(wù)而設(shè)計(jì)。它提供了一套統(tǒng)一的API,用于調(diào)度需保障執(zhí)行的延遲型異步任務(wù)(如數(shù)據(jù)同步、日志上傳),確保任務(wù)在應(yīng)用退出甚至設(shè)備重啟后仍能完成。作為Android平臺(tái)推薦的后臺(tái)任務(wù)調(diào)度框架,WorkManager平衡了系統(tǒng)資源限制與任務(wù)執(zhí)行可靠性,成為替代傳統(tǒng)方案(如AlarmManager、JobScheduler)的現(xiàn)代化解決方案。
1.2 核心設(shè)計(jì)目標(biāo)
- 有保證的執(zhí)行(Guaranteed Execution):通過(guò)SQLite數(shù)據(jù)庫(kù)持久化任務(wù)信息,即使應(yīng)用進(jìn)程被終止或設(shè)備重啟,系統(tǒng)也會(huì)在滿(mǎn)足條件后重新調(diào)度任務(wù)。
- 機(jī)會(huì)性執(zhí)行(Opportunistic Execution):在設(shè)備資源充足時(shí)(如充電狀態(tài)、空閑時(shí)段)立即執(zhí)行任務(wù),優(yōu)化電池壽命與用戶(hù)體驗(yàn)。
- 跨版本兼容性:自動(dòng)適配底層調(diào)度機(jī)制:
- API ≥23:使用
JobScheduler - API 14-22:降級(jí)為
AlarmManager+BroadcastReceiver
- API ≥23:使用
1.3 核心優(yōu)勢(shì)
- 簡(jiǎn)化多線(xiàn)程管理:自動(dòng)處理線(xiàn)程調(diào)度,開(kāi)發(fā)者只需關(guān)注
Worker中的業(yè)務(wù)邏輯。 - 靈活的任務(wù)鏈:支持順序或并行任務(wù)組合,例如“下載→處理→上傳”工作流可通過(guò)
beginWith().then()鏈?zhǔn)秸{(diào)用實(shí)現(xiàn)。 - 智能約束系統(tǒng):通過(guò)
Constraints.Builder設(shè)置執(zhí)行條件(如僅WiFi下執(zhí)行),避免無(wú)效喚醒。
1.4 典型適用場(chǎng)景
- 關(guān)鍵數(shù)據(jù)操作:用戶(hù)數(shù)據(jù)同步、數(shù)據(jù)庫(kù)備份(需保障執(zhí)行)。
- 資源敏感型任務(wù):大文件上傳(需
UNMETERED網(wǎng)絡(luò)約束)、圖片處理(需設(shè)備空閑)。 - 聚合執(zhí)行場(chǎng)景:日志批量上報(bào)(周期性任務(wù) + 彈性窗口
flexInterval)。
?? 注意:WorkManager 不適用于實(shí)時(shí)性要求高的任務(wù)(如即時(shí)通訊),此類(lèi)場(chǎng)景需改用前臺(tái)服務(wù)或推送機(jī)制。其核心價(jià)值在于為可延遲但必須完成的任務(wù)提供標(biāo)準(zhǔn)化、低能耗的調(diào)度框架。
2. 基礎(chǔ)使用?
2.1 ?添加依賴(lài)
在 build.gradle中添加依賴(lài)
dependencies {
implementation "androidx.work:work-runtime-ktx:2.9.1" // KTX 擴(kuò)展支持協(xié)程
}2.2 創(chuàng)建 Worker 類(lèi)?
繼承 CoroutineWorker(推薦協(xié)程)或 Worker,重寫(xiě) doWork()執(zhí)行任務(wù)邏輯
class UploadWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
val url = inputData.getString("KEY_URL") ?: return Result.failure()
try {
performUpload(url) // 執(zhí)行耗時(shí)操作
return Result.success(workDataOf("RESULT" to "Success"))
} catch (e: Exception) {
return Result.retry() // 失敗時(shí)重試
}
}
}?2.3 配置 WorkRequest?
??一次性任務(wù)??(OneTimeWorkRequest)
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED) // 需聯(lián)網(wǎng)
.setRequiresCharging(true) // 需充電
.build()
val uploadRequest = OneTimeWorkRequestBuilder<UploadWorker>()
.setInputData(workDataOf("KEY_URL" to "https://example.com"))
.setConstraints(constraints)
.setInitialDelay(10, TimeUnit.MINUTES) // 延遲啟動(dòng)
.build()周期性任務(wù)??(PeriodicWorkRequest,??最小間隔 15 分鐘??)
val syncRequest = PeriodicWorkRequestBuilder<SyncWorker>(15, TimeUnit.MINUTES).build()
2.4 提交任務(wù)??
通過(guò) WorkManager實(shí)例入隊(duì)任務(wù)
WorkManager.getInstance(context).enqueue(uploadRequest)
3. Constraints有哪些方法 ?
以下方法都是 Constraints.Builder 類(lèi)中的核心方法,用于為 WorkManager 的后臺(tái)任務(wù) (WorkRequest) 設(shè)置精確的執(zhí)行條件
這些方法可以分為幾大類(lèi):設(shè)備狀態(tài)約束、網(wǎng)絡(luò)約束和內(nèi)容URI觸發(fā)約束。
3.1 設(shè)備狀態(tài)約束 (Device State Constraints)
這類(lèi)方法確保任務(wù)只在設(shè)備處于特定狀態(tài)下才執(zhí)行,對(duì)省電和用戶(hù)體驗(yàn)至關(guān)重要。
3.1.1 setRequiresCharging(requiresCharging: Boolean): Builder
- 作用:設(shè)置任務(wù)是否必須在設(shè)備充電時(shí)才能運(yùn)行。
- 參數(shù):
requiresCharging- 設(shè)為true表示必須充電。 - 默認(rèn)值:
false(不要求充電)。 - 使用場(chǎng)景:非常適合執(zhí)行耗電量巨大的任務(wù),例如大規(guī)模數(shù)據(jù)同步、備份或復(fù)雜的文件處理,可以避免在用戶(hù)使用電池時(shí)消耗其電量。
3.1.2 setRequiresDeviceIdle(requiresDeviceIdle: Boolean): Builder
- 作用:設(shè)置任務(wù)是否必須在設(shè)備空閑時(shí)才能運(yùn)行。設(shè)備空閑通常指屏幕關(guān)閉一段時(shí)間且沒(méi)有用戶(hù)交互。
- 參數(shù):
requiresDeviceIdle- 設(shè)為true表示必須設(shè)備空閑。 - 默認(rèn)值:
false(不要求空閑)。 - API 要求:需要 Android 6.0 (API 級(jí)別 23) 或更高。
- 使用場(chǎng)景:用于執(zhí)行非常占用 CPU 或網(wǎng)絡(luò)資源的密集型任務(wù),確保不會(huì)在用戶(hù) actively 使用設(shè)備時(shí)造成卡頓或干擾。
系統(tǒng)判定設(shè)備空閑需滿(mǎn)足以下條件:
- ??屏幕關(guān)閉??:設(shè)備未處于亮屏狀態(tài)。
- ??無(wú)用戶(hù)交互??:用戶(hù)未操作設(shè)備(如觸摸、按鍵)持續(xù) ??≥30分鐘??。
- ??無(wú)活躍進(jìn)程??:無(wú)前臺(tái)應(yīng)用或高優(yōu)先級(jí)服務(wù)占用資源。
3.1.3 setRequiresBatteryNotLow(requiresBatteryNotLow: Boolean): Builder
- 作用:設(shè)置任務(wù)是否必須在設(shè)備電量充足時(shí)才能運(yùn)行。系統(tǒng)定義的“低電量”閾值通常約為 15%。
- 參數(shù):
requiresBatteryNotLow- 設(shè)為true表示必須電量充足。 - 默認(rèn)值:
false(不要求電量充足)。 - 使用場(chǎng)景:用于非緊急的后臺(tái)任務(wù),避免在用戶(hù)電量緊張時(shí)雪上加霜??梢院透邇?yōu)先度的通知任務(wù)結(jié)合,低電量時(shí)暫停普通同步。
3.1.4 setRequiresStorageNotLow(requiresStorageNotLow: Boolean): Builder
- 作用:設(shè)置任務(wù)是否必須在設(shè)備存儲(chǔ)空間充足時(shí)才能運(yùn)行。避免在存儲(chǔ)空間即將耗盡時(shí)執(zhí)行可能寫(xiě)入文件的操作。
- 參數(shù):
requiresStorageNotLow- 設(shè)為true表示必須存儲(chǔ)空間充足。 - 默認(rèn)值:
false(不要求存儲(chǔ)空間充足)。 - 使用場(chǎng)景:任何需要下載文件或緩存數(shù)據(jù)的任務(wù),如下載更新、保存圖片或日志文件等。
3.2 網(wǎng)絡(luò)約束 (Network Constraints)
這類(lèi)方法控制任務(wù)執(zhí)行所需的網(wǎng)絡(luò)環(huán)境。
3.2.1 setRequiredNetworkType(networkType: NetworkType): Builder
- 作用:設(shè)置任務(wù)執(zhí)行所需的基本網(wǎng)絡(luò)類(lèi)型。這是最常用的網(wǎng)絡(luò)約束方法。
- 參數(shù):
networkType- 枚舉值,包括:NOT_REQUIRED:不需要網(wǎng)絡(luò)(默認(rèn)值)。CONNECTED:設(shè)備有任何網(wǎng)絡(luò)連接即可(Wi-Fi 或移動(dòng)數(shù)據(jù))。UNMETERED:需要不計(jì)流量的網(wǎng)絡(luò)(如 Wi-Fi)。METERED:需要按流量計(jì)費(fèi)的網(wǎng)絡(luò)(如移動(dòng)數(shù)據(jù))。NOT_ROAMING:需要非漫游網(wǎng)絡(luò)。
- 使用場(chǎng)景:
UNMETERED:用于下載大文件、更新應(yīng)用、上傳日志等大量數(shù)據(jù)傳輸操作。CONNECTED:用于輕量級(jí)的網(wǎng)絡(luò)請(qǐng)求,如發(fā)送即時(shí)消息、獲取小型配置更新等。METERED:用于需要明確使用移動(dòng)數(shù)據(jù)的場(chǎng)景。
3.2.2 setRequiredNetworkRequest(networkRequest: NetworkRequest, networkType: NetworkType): Builder
- 作用:提供一個(gè)更高級(jí)、更精細(xì)的網(wǎng)絡(luò)約束方式(基于 Android 的
NetworkRequestAPI)。它允許你指定更復(fù)雜的網(wǎng)絡(luò)能力要求,例如帶寬、延遲等。在較新的 Android 版本(API 28+)上使用此設(shè)置,在舊版本上會(huì)自動(dòng)回退到您指定的networkType。 - 限制:不支持設(shè)置了
NetworkSpecifier(如指定特定 Wi-Fi SSID)或setIncludeOtherUidNetworks的請(qǐng)求,傳入此類(lèi)請(qǐng)求會(huì)拋出IllegalArgumentException。 - API 要求:需要 Android 5.0 (API 級(jí)別 21) 或更高,但其高級(jí)功能在更高版本上才有效。
- 使用場(chǎng)景:需要非常特定網(wǎng)絡(luò)條件的專(zhuān)業(yè)應(yīng)用,例如視頻會(huì)議應(yīng)用需要高上行帶寬的網(wǎng)絡(luò),或游戲需要低延遲網(wǎng)絡(luò)。
3.3 內(nèi)容URI觸發(fā)約束 (Content URI Triggers)
這是一組非常強(qiáng)大的約束,允許任務(wù)在你關(guān)注的特定數(shù)據(jù)發(fā)生變化時(shí)被觸發(fā),類(lèi)似于數(shù)據(jù)庫(kù)的觸發(fā)器。
3.3.1 addContentUriTrigger(uri: Uri, triggerForDescendants: Boolean): Builder
- 作用:添加一個(gè)要監(jiān)聽(tīng)的內(nèi)容提供者 (ContentProvider) 的 URI。當(dāng)此 URI 代表的數(shù)據(jù)發(fā)生變化(插入、更新、刪除)時(shí),會(huì)觸發(fā)任務(wù)運(yùn)行。
- 參數(shù):
uri:要監(jiān)聽(tīng)的內(nèi)容 URI(例如content://media/external/images/media)。triggerForDescendants:如果為true,則監(jiān)聽(tīng)該 URI 及其所有子路徑的變化;如果為false,則只監(jiān)聽(tīng)該精確 URI。
- API 要求:需要 Android 7.0 (API 級(jí)別 24) 或更高。
- 使用場(chǎng)景:
- 監(jiān)聽(tīng)媒體庫(kù)的變化,當(dāng)有新圖片或視頻時(shí)執(zhí)行某些處理。
- 監(jiān)聽(tīng)自定義 ContentProvider 的數(shù)據(jù)變化,實(shí)現(xiàn)數(shù)據(jù)驅(qū)動(dòng)型的任務(wù)調(diào)度。
3.3.2 setTriggerContentUpdateDelay(…) 與 setTriggerContentMaxDelay(…)
- 作用:這兩個(gè)方法用于控制觸發(fā)延遲,以避免在數(shù)據(jù)頻繁變化時(shí)任務(wù)被過(guò)于頻繁地觸發(fā)。
setTriggerContentUpdateDelay:設(shè)置從檢測(cè)到內(nèi)容變化到調(diào)度任務(wù)之間的最小等待時(shí)間。如果在此期間內(nèi)容再次變化,計(jì)時(shí)器會(huì)重置。setTriggerContentMaxDelay:設(shè)置從第一次檢測(cè)到內(nèi)容變化到調(diào)度任務(wù)之間的最大等待時(shí)間。即使內(nèi)容一直在變化,超過(guò)此時(shí)間后任務(wù)也一定會(huì)被調(diào)度。
- 重載方法:兩者都提供了接受
(Long, TimeUnit)和(Duration)參數(shù)的方法,后者是更現(xiàn)代的 Java Time API。 - API 要求:需要 Android 7.0 (API 級(jí)別 24) 或更高。
- 使用場(chǎng)景:例如,一個(gè)文檔管理應(yīng)用在用戶(hù)批量刪除文件時(shí),文件變化事件會(huì)連續(xù)觸發(fā)。設(shè)置一個(gè)最大延遲(如 1 分鐘),可以確保任務(wù)最終會(huì)執(zhí)行一次以處理所有更改,而不是為每個(gè)文件的刪除都執(zhí)行一次。
4. CoroutineWorker和Worker的區(qū)別
CoroutineWorker 和 Worker 是兩種核心的任務(wù)執(zhí)行基類(lèi),它們的設(shè)計(jì)目標(biāo)、實(shí)現(xiàn)機(jī)制和適用場(chǎng)景存在顯著差異。
4.11基礎(chǔ)架構(gòu)與線(xiàn)程模型
Worker
基于 Java 的線(xiàn)程池和回調(diào)機(jī)制。其doWork()方法在后臺(tái)線(xiàn)程中同步執(zhí)行,需避免阻塞主線(xiàn)程。若任務(wù)耗時(shí)較長(zhǎng),可能占用線(xiàn)程池資源,影響其他任務(wù)調(diào)度。CoroutineWorker
基于 Kotlin 協(xié)程實(shí)現(xiàn)。doWork()是掛起函數(shù)(suspend),在協(xié)程作用域內(nèi)異步執(zhí)行。任務(wù)可被掛起(如等待 I/O 操作),釋放底層線(xiàn)程供其他任務(wù)使用,顯著提升資源利用率。
4.2資源消耗與并發(fā)能力
Worker
每個(gè)任務(wù)獨(dú)占一個(gè)線(xiàn)程,大量并發(fā)任務(wù)時(shí)需創(chuàng)建多個(gè)線(xiàn)程,消耗較多內(nèi)存(每個(gè)線(xiàn)程約 1MB ??臻g)。線(xiàn)程切換開(kāi)銷(xiāo)在高并發(fā)場(chǎng)景下可能成為瓶頸。CoroutineWorker
協(xié)程輕量級(jí)(內(nèi)存占用約數(shù)十 KB),單線(xiàn)程可調(diào)度數(shù)萬(wàn)協(xié)程。適合高并發(fā) I/O 操作(如網(wǎng)絡(luò)請(qǐng)求、數(shù)據(jù)庫(kù)讀寫(xiě)),避免線(xiàn)程資源浪費(fèi)。
4.3 CoroutineWorker和Worker的doWork方法中,需要單獨(dú)啟動(dòng)一個(gè)IO線(xiàn)程再執(zhí)行嗎 ?
4.3.1 ??Worker(傳統(tǒng) Java 線(xiàn)程模型)?
無(wú)需額外啟動(dòng) IO 線(xiàn)程??:
Worker.doWork()??默認(rèn)在 WorkManager 管理的后臺(tái)線(xiàn)程池中執(zhí)行??(非主線(xiàn)程)。該線(xiàn)程池由 Executor實(shí)現(xiàn),默認(rèn)大小為 2-4 個(gè)線(xiàn)程(基于設(shè)備 CPU 核心數(shù))
class MyWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
override fun doWork(): Result {
// 直接執(zhí)行同步 I/O 操作(已在后臺(tái)線(xiàn)程)
val data = downloadFileSync("https://example.com/data")
return Result.success()
}
}4.3.2 ??CoroutineWorker(協(xié)程模型)?
??無(wú)需額外啟動(dòng)線(xiàn)程,但需指定調(diào)度器??:
CoroutineWorker.doWork()是掛起函數(shù),??默認(rèn)運(yùn)行在 Dispatchers.Default??(計(jì)算密集型線(xiàn)程池)。若需 I/O 操作(如網(wǎng)絡(luò)請(qǐng)求、文件讀寫(xiě)),應(yīng)使用 withContext(Dispatchers.IO)切換到 I/O 調(diào)度器。
class MyCoroutineWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
// 切換到 IO 調(diào)度器執(zhí)行阻塞操作
val data = withContext(Dispatchers.IO) {
downloadFile("https://example.com/data")
}
return Result.success()
}
}從技術(shù)趨勢(shì)看,
CoroutineWorker代表了 Android 異步任務(wù)的未來(lái)方向,尤其在資源利用率和代碼可維護(hù)性上優(yōu)勢(shì)明顯。
5. PeriodicWorkRequestBuilder和OneTimeWorkRequestBuilder的區(qū)別
PeriodicWorkRequestBuilder 和 OneTimeWorkRequestBuilder 是定義后臺(tái)任務(wù)的兩類(lèi)核心構(gòu)建器,它們的主要區(qū)別在于任務(wù)執(zhí)行模式的設(shè)計(jì)目標(biāo)。以下是二者的詳細(xì)對(duì)比及 WorkManager 中的其他構(gòu)建器類(lèi)型說(shuō)明:
5.1 核心區(qū)別:執(zhí)行模式
| 特性 | OneTimeWorkRequestBuilder | PeriodicWorkRequestBuilder |
|---|---|---|
| 任務(wù)類(lèi)型 | 一次性任務(wù)(執(zhí)行后終止) | 周期性任務(wù)(按固定間隔重復(fù)執(zhí)行) |
| 最小執(zhí)行間隔 | 無(wú)限制 | ≥15分鐘(受系統(tǒng)強(qiáng)制限制) |
| 適用場(chǎng)景 | 單次數(shù)據(jù)上傳、即時(shí)操作處理 | 定期數(shù)據(jù)同步、日志備份、周期檢查 |
| 靈活性 | 支持復(fù)雜約束鏈(如任務(wù)鏈 beginWith().then()) | 僅支持獨(dú)立任務(wù)(不可鏈?zhǔn)秸{(diào)用) |
| 延遲配置 | 支持精確延遲(如 setInitialDelay(10, MINUTES)) | 僅支持重復(fù)間隔(repeatInterval)和彈性窗口(flexInterval) |
?? 周期性任務(wù)注意事項(xiàng):
- 若周期任務(wù)執(zhí)行時(shí)約束未滿(mǎn)足(如無(wú)網(wǎng)絡(luò)),系統(tǒng)會(huì)跳過(guò)本次執(zhí)行,不會(huì)自動(dòng)補(bǔ)償,需等待下一周期。
- 彈性窗口(
flexInterval)允許任務(wù)在周期末尾的彈性時(shí)段內(nèi)執(zhí)行(如最后15分鐘),優(yōu)化資源調(diào)度。
5.2 高級(jí)配置差異
- 重試策略
OneTimeWorkRequestBuilder:可通過(guò)setBackoffCriteria()配置指數(shù)退避策略(如失敗后延遲重試)。PeriodicWorkRequestBuilder:不支持重試策略,失敗后需等待下一周期。
- 加速任務(wù)(Expedited Work)
- 僅
OneTimeWorkRequestBuilder支持setExpedited(),用于緊急任務(wù)(如支付操作),系統(tǒng)會(huì)優(yōu)先分配資源。 - 周期性任務(wù)無(wú)法加速執(zhí)行。
- 僅
5.3 OneTimeWorkRequestBuilder怎么使用
val constraints = Constraints.Builder()
.build()
val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
.setConstraints(constraints)
.setInitialDelay(15, TimeUnit.MINUTES) //任務(wù)延遲啟動(dòng)(例如 15 分鐘后)
.setBackoffCriteria( //配置失敗后的指數(shù)退避重試
BackoffPolicy.EXPONENTIAL, // 或 LINEAR
OneTimeWorkRequest.MIN_BACKOFF_MILLIS, // 最小延遲 10 秒
TimeUnit.MILLISECONDS
)
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) //加急任務(wù)
.build()5.3.1 setBackoffCriteria中EXPONENTIAL和LINEAR的區(qū)別
??EXPONENTIAL(指數(shù)退避)?? 和 ??LINEAR(線(xiàn)性退避)?? 是兩種不同的重試延遲策略,用于控制任務(wù)失敗后重新調(diào)度的等待時(shí)間增長(zhǎng)方式。
- LINEAR? : ?延遲時(shí)間按??固定值線(xiàn)性增加??:延遲時(shí)間 = 初始延遲 × 重試次數(shù)
- EXPONENTIAL : 延遲時(shí)間按??指數(shù)倍數(shù)增長(zhǎng) : 延遲時(shí)間 = 初始延遲 × 2^(重試次數(shù)-1)
5.3.2 setExpedited
- RUN_AS_NON_EXPEDITED_WORK_REQUEST
- 配額足夠時(shí)??:
- 任務(wù)作為加急任務(wù)??立即執(zhí)行??,享受高優(yōu)先級(jí)調(diào)度(低延遲、抗省電限制)。
- ??配額不足時(shí)??:
- 任務(wù)??自動(dòng)降級(jí)為普通后臺(tái)任務(wù)??,按標(biāo)準(zhǔn) WorkRequest流程執(zhí)行:
- 需等待約束條件滿(mǎn)足(如聯(lián)網(wǎng)、充電)。
- 可能延遲執(zhí)行(無(wú)加急優(yōu)先級(jí))
- 配額足夠時(shí)??:
- DROP_WORK_REQUEST??
- 配合足夠時(shí) :
- 任務(wù)作為加急任務(wù)??立即執(zhí)行??,享受高優(yōu)先級(jí)調(diào)度(低延遲、抗省電限制)。
- 配額不足時(shí)??直接丟棄任務(wù)??,不會(huì)轉(zhuǎn)為普通任務(wù)
- 配合足夠時(shí) :
加急任務(wù)(RUN_AS_NON_EXPEDITED_WORK_REQUEST)的優(yōu)先級(jí)高于延遲設(shè)置??(setInitialDelay)
加急任務(wù)會(huì)嘗試??立即執(zhí)行??,僅受系統(tǒng)配額限制(如設(shè)備資源緊張時(shí)可能延遲)
若當(dāng)前配額充足(如應(yīng)用在前臺(tái)或系統(tǒng)負(fù)載低),加急任務(wù)會(huì)忽略延遲時(shí)間直接啟動(dòng)
6. WorkManager怎么取消任務(wù)
取消任務(wù)需根據(jù)任務(wù)標(biāo)識(shí)類(lèi)型選擇對(duì)應(yīng)方法
6.1 通過(guò)任務(wù) ID 取消
每個(gè) WorkRequest 創(chuàng)建時(shí)自動(dòng)生成唯一 ID (UUID),適用于精確取消單個(gè)任務(wù)。
val workRequest = OneTimeWorkRequestBuilder<MyWorker>().build() WorkManager.getInstance(context).enqueue(workRequest) // 取消任務(wù) WorkManager.getInstance(context).cancelWorkById(workRequest.id)
適用場(chǎng)景:明確知道目標(biāo)任務(wù)的 ID 時(shí)使用。
6.2 通過(guò)標(biāo)簽 (Tag) 取消
為任務(wù)添加標(biāo)簽后,可批量取消同標(biāo)簽的所有任務(wù):
val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
.addTag("data_sync") // 添加標(biāo)簽
.build()
// 取消所有帶此標(biāo)簽的任務(wù)
WorkManager.getInstance(context).cancelAllWorkByTag("data_sync")優(yōu)勢(shì):適用于邏輯分組任務(wù)(如“所有數(shù)據(jù)同步任務(wù)”)。
6.3 取消唯一任務(wù) (Unique Work)
唯一任務(wù)通過(guò)名稱(chēng) (uniqueWorkName) 標(biāo)識(shí),同一名稱(chēng)僅允許一個(gè)實(shí)例運(yùn)行:
val workRequest = OneTimeWorkRequestBuilder<MyWorker>().build()
// 提交唯一任務(wù)
WorkManager.getInstance(context).enqueueUniqueWork(
"unique_sync_task",
ExistingWorkPolicy.REPLACE,
workRequest
)
// 通過(guò)唯一名稱(chēng)取消
WorkManager.getInstance(context).cancelUniqueWork("unique_sync_task")策略說(shuō)明:
ExistingWorkPolicy.REPLACE:新任務(wù)自動(dòng)取消舊任務(wù)。- 適用于防重復(fù)任務(wù)(如定時(shí)數(shù)據(jù)同步)。
6.4 取消所有任務(wù)
清理整個(gè) WorkManager 隊(duì)列:
WorkManager.getInstance(context).cancelAllWork()
慎用:會(huì)取消所有未完成的任務(wù)(包括周期任務(wù))。
6.5 取消后的任務(wù)行為
- 狀態(tài)變更:任務(wù)狀態(tài)變?yōu)?
CANCELLED,但doWork()中的代碼不會(huì)立即停止。 - 資源釋放:需在 Worker 中主動(dòng)檢查取消信號(hào):關(guān)鍵點(diǎn):
class MyWorker(context: Context, params: WorkerParameters) : Worker(context, params) { override fun doWork(): Result { while (!isStopped) { // 循環(huán)中檢查取消狀態(tài) // 執(zhí)行邏輯 } return Result.success() } override fun onStopped() { super.onStopped() // 釋放資源(如關(guān)閉數(shù)據(jù)庫(kù)連接) } }isStopped:檢測(cè)任務(wù)是否被取消。onStopped():收到取消信號(hào)時(shí)回調(diào),用于清理資源。
6.5.1 通過(guò)workManager.getWorkInfosByTag,怎么判斷是否有某個(gè)Work還未執(zhí)行 ?
val workManager = WorkManager.getInstance(context)
val tag = "YOUR_TAG" // 替換為實(shí)際標(biāo)簽
// 異步監(jiān)聽(tīng)方式(推薦)
workManager.getWorkInfosByTagLiveData(tag).observe(this) { workInfos ->
val hasUnfinishedWork = workInfos.any { workInfo ->
workInfo.state == WorkInfo.State.ENQUEUED ||
workInfo.state == WorkInfo.State.BLOCKED
}
if (hasUnfinishedWork) {
Log.d("WorkStatus", "存在未執(zhí)行的任務(wù)")
}
}
// 同步查詢(xún)方式(需在后臺(tái)線(xiàn)程執(zhí)行)
val workInfos = workManager.getWorkInfosByTag(tag).get()
val unfinishedWorkExists = workInfos.any { workInfo ->
workInfo.state == WorkInfo.State.ENQUEUED ||
workInfo.state == WorkInfo.State.BLOCKED
}7. 更多內(nèi)容
有關(guān)Doze低功耗模式下的WorkManager,詳見(jiàn) : Android Doze低電耗休眠模式 與 WorkManager
到此這篇關(guān)于Android WorkManager的概念和使用詳細(xì)指南的文章就介紹到這了,更多相關(guān)Android WorkManager使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Android使用WorkManager實(shí)現(xiàn)緩存清理的方案
- android kotlin集成WorkManager實(shí)現(xiàn)定時(shí)獲取數(shù)據(jù)的步驟
- Android WorkManager使用以及源碼分析
- Android WorkManager實(shí)現(xiàn)后臺(tái)定時(shí)任務(wù)流程詳解
- Android?Jetpack庫(kù)重要組件WorkManager的使用
- Android開(kāi)發(fā)Jetpack組件WorkManager用例詳解
- Android使用Kotlin API實(shí)踐WorkManager
- Android WorkManager淺談
相關(guān)文章
Android端權(quán)限隱私的合規(guī)化處理實(shí)戰(zhàn)記錄
大家應(yīng)該都發(fā)現(xiàn)了,現(xiàn)在很多應(yīng)用市場(chǎng)都要求應(yīng)用上架需要用戶(hù)協(xié)議,這篇文章主要給大家介紹了關(guān)于Android端權(quán)限隱私合規(guī)化處理的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-08-08
Android中通過(guò)訪(fǎng)問(wèn)本地相冊(cè)或者相機(jī)設(shè)置用戶(hù)頭像實(shí)例
本篇文章主要介紹了Android中通過(guò)訪(fǎng)問(wèn)本地相冊(cè)或者相機(jī)設(shè)置用戶(hù)頭像,具有一定的參考價(jià)值,有興趣的可以了解一下。2017-01-01
Android人臉識(shí)別Demo豎屏YUV方向調(diào)整和圖片保存(分享)
下面小編就為大家分享一篇Android人臉識(shí)別Demo實(shí)現(xiàn)豎屏YUV方向調(diào)整和圖片保存的方法。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
Android實(shí)現(xiàn)簡(jiǎn)單手電筒功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)簡(jiǎn)單手電筒,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09
Android5.1 取消錄制屏幕跳出的權(quán)限對(duì)話(huà)框問(wèn)題
這篇文章主要介紹了Android5.1 取消錄制屏幕跳出的權(quán)限對(duì)話(huà)框問(wèn)題,需要的朋友可以參考下2017-04-04
Android項(xiàng)目實(shí)現(xiàn)視頻播放器
這篇文章主要為大家詳細(xì)介紹了Android項(xiàng)目實(shí)現(xiàn)視頻播放器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-03-03
Android React-Native通信數(shù)據(jù)模型分析
這篇文章主要介紹了Android React-Native通信數(shù)據(jù)模型分析的相關(guān)資料,需要的朋友可以參考下2016-10-10
Android實(shí)現(xiàn)鍵盤(pán)彈出界面上移的實(shí)現(xiàn)思路
這篇文章主要介紹了Android實(shí)現(xiàn)鍵盤(pán)彈出界面上移的實(shí)現(xiàn)思路,需要的朋友可以參考下2018-04-04
Android通過(guò)Dialog實(shí)現(xiàn)全屏的示例代碼
在項(xiàng)目的實(shí)際開(kāi)發(fā)中會(huì)碰到有些View需要橫屏全屏的情況,如果跳轉(zhuǎn)到新的Activity或Fragment來(lái)展示橫屏全屏,有些進(jìn)度、狀態(tài)等攜帶過(guò)去又很麻煩,這樣的情況下通過(guò)Dialog實(shí)現(xiàn)全屏就是一個(gè)選擇,所以本文給大家介紹了Android如何通過(guò)Dialog實(shí)現(xiàn)全屏,需要的朋友可以參考下2025-10-10

