Android開(kāi)發(fā)Jetpack組件WorkManager用例詳解
一、簡(jiǎn)介
WorkManager 用于處理 Android 后臺(tái)任務(wù)。我們只需要設(shè)置好任務(wù)內(nèi)容、何時(shí)執(zhí)行,剩下的工作就可以完全交給系統(tǒng)處理。它會(huì)自動(dòng)向下兼容,在不同的 Android 版本上采用不同的實(shí)現(xiàn)方案。
由于是交給系統(tǒng)調(diào)度的,它可以保證應(yīng)用退出甚至手機(jī)重啟后,任務(wù)依然能夠得到執(zhí)行。WorkManager 很適合執(zhí)行一些定期和服務(wù)器交互的任務(wù),比如周期性的同步數(shù)據(jù)等等。并且,WorkManager 還支持周期性任務(wù)、鏈?zhǔn)饺蝿?wù)。
需要注意的是,WorkManager 不能保證任務(wù)一定能夠準(zhǔn)時(shí)執(zhí)行,這是因?yàn)橄到y(tǒng)為了減少電量消耗,會(huì)將觸發(fā)事件臨近的幾個(gè)任務(wù)放在一起執(zhí)行,以減少 CPU 被喚醒的次數(shù),延長(zhǎng)電池使用時(shí)間。
另外,在國(guó)產(chǎn)手機(jī)上 WorkManager 可能無(wú)法正常運(yùn)行,這是因?yàn)榻^大多數(shù)手機(jī)廠商定制 Android 系統(tǒng)時(shí),會(huì)添加一個(gè)“一鍵關(guān)閉”的功能,這樣被殺死后的應(yīng)用程序,既無(wú)法接收廣播,也不能運(yùn)行 WorkManager 的后臺(tái)任務(wù)。國(guó)產(chǎn)手機(jī)增加此功能也是迫于無(wú)奈,主要是因?yàn)槭忻嫔嫌刑嗟膼阂鈶?yīng)用想要霸占后臺(tái)。所以,我們?cè)趪?guó)產(chǎn)手機(jī)上不要使用 WorkManager 去實(shí)現(xiàn)核心功能。
二、導(dǎo)入
在 app/build.gradle 中添加依賴:
implementation 'androidx.work:work-runtime:2.3.2'
三、基本使用
WorkManager 的用法分為三步:
- 定義一個(gè)后臺(tái)任務(wù)
- 配置任務(wù)運(yùn)行條件
- 將任務(wù)傳給 WorkManager
3.1 定義后臺(tái)任務(wù)
創(chuàng)建一個(gè) SimpleWorker 類(lèi),繼承自 Worker:
class SimpleWorker(context: Context, params: WorkerParameters) : Worker(context, params) { override fun doWork(): Result { Log.d("~~~", "do something") return Result.success() } }
Result.success()
表示任務(wù)執(zhí)行成功
Result.failure()
表示任務(wù)執(zhí)行失敗
Result.retry()
表示任務(wù)需要重試。這個(gè)方法需要配合任務(wù)重試配置一起使用
3.2 配置任務(wù)運(yùn)行條件
3.2.1 只需執(zhí)行一次的任務(wù)
使用 OneTimeWorkRequest 構(gòu)建只需執(zhí)行一次的任務(wù)
val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java).build()
3.2.2 周期性執(zhí)行的任務(wù)
使用 PeriodicWorkRequest 構(gòu)建周期性執(zhí)行的任務(wù)
val request = PeriodicWorkRequest.Builder(SimpleWorker::class.java, 15, TimeUnit.MINUTES).build()
為了減少耗電量,PeriodicWorkRequest 要求任務(wù)執(zhí)行周期不得短于十五分鐘,查看源碼可以發(fā)現(xiàn),如果傳入的值短于十五分鐘,系統(tǒng)會(huì)打印一條警告,然后自動(dòng)將周期設(shè)置成十五分鐘:
public static final long MIN_PERIODIC_INTERVAL_MILLIS = 15 * 60 * 1000L; // 15 minutes. /** * Sets the periodic interval for this unit of work. * * @param intervalDuration The interval in milliseconds */ public void setPeriodic(long intervalDuration) { if (intervalDuration < MIN_PERIODIC_INTERVAL_MILLIS) { Logger.get().warning(TAG, String.format( "Interval duration lesser than minimum allowed value; Changed to %s", MIN_PERIODIC_INTERVAL_MILLIS)); intervalDuration = MIN_PERIODIC_INTERVAL_MILLIS; } setPeriodic(intervalDuration, intervalDuration); }
3.3 將任務(wù)傳給 WorkManager
WorkManager.getInstance(this).enqueue(request)
這就是 WorkManager 的基本使用。
四、高級(jí)配置
4.1 設(shè)置任務(wù)延遲執(zhí)行
通過(guò) setInitialDelay 方法設(shè)置延遲時(shí)間
val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java) .setInitialDelay(5, TimeUnit.MINUTES) .build()
4.2 給任務(wù)添加標(biāo)簽
通過(guò) addTag 方法添加標(biāo)簽:
val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java) .addTag("simple") .build()
添加標(biāo)簽的作用是,方便我們根據(jù)標(biāo)簽取消任務(wù)。
4.3 取消任務(wù)
4.3.1 根據(jù)標(biāo)簽取消任務(wù)
WorkManager.getInstance(this).cancelAllWorkByTag("simple")
4.3.2 根據(jù) request 的 id 取消任務(wù)
WorkManager.getInstance(this).cancelWorkById(request.id)
4.3.3 取消所有任務(wù)
WorkManager.getInstance(this).cancelAllWork()
4.4 任務(wù)重試
通過(guò) setBackoffCriteria 配置任務(wù)重試:
val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java) ? ? .setBackoffCriteria(BackoffPolicy.LINEAR, 10, TimeUnit.SECONDS) ? ? .build()
前文說(shuō)到,Result.retry() 表示任務(wù)需要重試,這個(gè)方法需要配合任務(wù)重試配置一起使用。任務(wù)重試配置就是指這個(gè) setBackoffCriteria 方法,它傳入了三個(gè)值,第二個(gè)值和第三個(gè)值表示重試時(shí)間配置。第一個(gè)值表示重試延遲的形式,有兩個(gè)值可供選擇:
- BackoffPolicy.LINEAR 重試時(shí)間每次呈線性增長(zhǎng),按照此例中的配置,每次重試時(shí)間就是 10s,20s,30s,40s…
- BackoffPolicy.EXPONENTIAL 重試時(shí)間每次呈指數(shù)級(jí)增長(zhǎng),按照此例中的配置,每次重試時(shí)間就是 10s,20s,40s,80s…
4.5 監(jiān)聽(tīng)任務(wù)結(jié)果
WorkManager.getInstance(this).getWorkInfoByIdLiveData(request.id).observe(this) { ? ? Log.d("~~~", "state = ${it.state}, tags = ${it.tags.toList()}") ? ? when (it.state) { ? ? ? ? WorkInfo.State.SUCCEEDED -> Log.d("~~~", "success") ? ? ? ? WorkInfo.State.FAILED -> Log.d("~~~", "fail") ? ? ? ? WorkInfo.State.RUNNING -> Log.d("~~~", "running") ? ? ? ? WorkInfo.State.ENQUEUED -> Log.d("~~~", "enqueued") ? ? ? ? WorkInfo.State.CANCELLED -> Log.d("~~~", "cancelled") ? ? ? ? WorkInfo.State.BLOCKED -> Log.d("~~~", "blocked") ? ? } }
首先通過(guò) getWorkInfoByIdLiveData 獲得任務(wù)信息的 LiveData<WorkInfo> 數(shù)據(jù),然后觀察此數(shù)據(jù)即可。也可以通過(guò) getWorkInfosByTagLiveData 獲得相同 Tag 的 LiveData<List<WorkInfo>>,觀察這個(gè)任務(wù)信息列表。通過(guò) WorkInfo 的 getState 方法獲取任務(wù)狀態(tài),主要用到的狀態(tài)有 WorkInfo.State.SUCCEEDED 和 WorkInfo.State.FAILED,標(biāo)志著任務(wù)的成功和失敗。
4.6 傳遞數(shù)據(jù)
val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java) ? ? .setInputData(Data.Builder().apply { ? ? ? ? putString("key", "value") ? ? }.build()) ? ? .build()
SimpleWorker 類(lèi)中讀取此數(shù)據(jù):
inputData.getString("key")
4.7 鏈?zhǔn)饺蝿?wù)
val first = OneTimeWorkRequest.Builder(SimpleWorker::class.java) ? ? .build() val second = OneTimeWorkRequest.Builder(SimpleWorker::class.java) ? ? .build() val third = OneTimeWorkRequest.Builder(SimpleWorker::class.java) ? ? .build() WorkManager.getInstance(this) ? ? .beginWith(first) ? ? .then(second) ? ? .then(third) ? ? .enqueue()
通過(guò) beginWith 發(fā)起鏈?zhǔn)饺蝿?wù),然后后綴 then 即可,任務(wù)會(huì)按照連接順序依次執(zhí)行。WorkManager 要求必須在上一個(gè)任務(wù)執(zhí)行成功后,才會(huì)執(zhí)行下一個(gè)任務(wù)。也就是說(shuō)任何一個(gè)任務(wù)的失敗都會(huì)導(dǎo)致鏈?zhǔn)饺蝿?wù)的中斷。
以上就是Android開(kāi)發(fā)Jetpack組件WorkManager用例詳解的詳細(xì)內(nèi)容,更多關(guān)于Android Jetpack組件WorkManager的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
淺扒Android動(dòng)態(tài)設(shè)置字體大小的示例
本篇文章主要介紹了淺扒Android動(dòng)態(tài)設(shè)置字體大小的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-12-12深入分析Android NFC技術(shù) android nfc開(kāi)發(fā)
本篇文章我們對(duì)android開(kāi)發(fā)中nfc技術(shù)做了全面的原理分析以及實(shí)現(xiàn)過(guò)程,需要的讀者們一起參考一下吧。2017-11-11Android Flutter實(shí)現(xiàn)興趣標(biāo)簽選擇功能
我們?cè)谑状问褂脙?nèi)容類(lèi) App 的時(shí)候,不少都會(huì)讓我們選擇個(gè)人偏好,通過(guò)這些標(biāo)簽選擇可以預(yù)先知道用戶的偏好信息。我們本篇就來(lái)看看 Flutter 如何實(shí)現(xiàn)興趣標(biāo)簽的選擇,需要的可以參考一下2022-11-11Android控件RefreshableView實(shí)現(xiàn)下拉刷新
這篇文章主要為大家詳細(xì)介紹了Android控件RefreshableView實(shí)現(xiàn)下拉刷新,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11Android 判斷網(wǎng)絡(luò)狀態(tài)對(duì)音頻靜音的實(shí)現(xiàn)方法
最近小編做項(xiàng)目遇到這樣的需求,需要根據(jù)當(dāng)前場(chǎng)景讓app變的智能,讓app根據(jù)使用者當(dāng)前網(wǎng)絡(luò)狀態(tài),自動(dòng)記性靜音等操作,具體怎么實(shí)現(xiàn)呢?下面小編給大家分享實(shí)例代碼,需要的朋友參考下吧2018-10-10Android Drawerlayout側(cè)拉欄事件傳遞問(wèn)題的解決方法
這篇文章主要為大家詳細(xì)介紹了Android Drawerlayout側(cè)拉欄事件傳遞問(wèn)題的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11Android 如何實(shí)現(xiàn)exclude aar包中的某個(gè)jar包
這篇文章主要介紹了Android 如何實(shí)現(xiàn)exclude aar包中的某個(gè)jar包,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03android實(shí)現(xiàn)通過(guò)NFC讀取卡號(hào)
這篇文章主要介紹了android實(shí)現(xiàn)通過(guò)NFC讀取卡號(hào),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09