網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
Android?WorkManager實(shí)現(xiàn)后臺(tái)定時(shí)任務(wù)流程詳解_Android
作者:Mr?YiRan ? 更新時(shí)間: 2023-03-27 編程語(yǔ)言WorkManager和Service并不相同,也沒(méi)有直接的聯(lián)系。Service是Android系統(tǒng)四大組件之一,它沒(méi)有被銷毀的情況下是一直保持在后臺(tái)運(yùn)行的。而WorkManager只是一個(gè)處理定時(shí)任務(wù)的工具,它可以保證即使在應(yīng)用退出甚至手機(jī)重啟的情況下,之前注冊(cè)的任務(wù)仍然將會(huì)得到執(zhí)行,因此WorkManager很適合用于執(zhí)行一些定期和服務(wù)器進(jìn)行交互的任務(wù),比如周期性地同步數(shù)據(jù)等等。
使用WorkManager注冊(cè)的周期性任務(wù)不能保證一定會(huì)準(zhǔn)時(shí)執(zhí)行,這是因?yàn)橄到y(tǒng)為了減少電量消耗,可能會(huì)將觸發(fā)時(shí)間臨近的幾個(gè)任務(wù)放在一起執(zhí)行,這樣可以大幅度減少CPU被喚醒的次數(shù),從而有效延長(zhǎng)電池的使用時(shí)間。
WorkManager的基本用法
先添加依賴
?implementation 'androidx.work:work-runtime-ktx:2.2.0'
WorkManager的基本用法主要分為以下3步:
- 定義一個(gè)后臺(tái)任務(wù),并實(shí)現(xiàn)具體的任務(wù)邏輯
- 配置該后臺(tái)任務(wù)的運(yùn)行條件和約束信息,并構(gòu)建后臺(tái)任務(wù)請(qǐng)求
- 將該后臺(tái)任務(wù)請(qǐng)求傳入WorkManager的enqueue()方法中,系統(tǒng)會(huì)在合適的時(shí)間運(yùn)行
第一步定義一個(gè)后臺(tái)任務(wù),這里創(chuàng)建一個(gè)SimpleWorker類,代碼如下所示:
class SimpleWorker(context: Context,params:WorkerParameters):Worker(context,params) {
override fun doWork(): Result {
Log.d("SimpleWorker", "do Work in SimpleWorker")
return Result.success()//成功就返回Result.success()
}
}
首先每一個(gè)后臺(tái)任務(wù)都必須繼承自Worker類,并調(diào)用它唯一的構(gòu)造函數(shù)。然后重寫父類中的doWork()方法,在這個(gè)方法中編寫具體的后臺(tái)任務(wù)邏輯。
第二步配置該后臺(tái)任務(wù)的運(yùn)行條件和約束信息
val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java).build()
可以看到,只需要把剛才創(chuàng)建的后臺(tái)任務(wù)所對(duì)應(yīng)的Class對(duì)象傳入 OneTimeWorkRequest.Builder的構(gòu)造函數(shù)當(dāng)中,然后調(diào)用build()方法就可以完成構(gòu)建。
OneTimeWorkRequest.Builder是WorkRequest.Builder的子類,用于構(gòu)建單次運(yùn)行的后臺(tái)任務(wù)請(qǐng)求。WorkRequest.Builder還有另外一個(gè)子類PeriodicWorkRequest.Builder,可用于構(gòu)建周期性運(yùn)行的后臺(tái)任務(wù)請(qǐng)求,但是為了降低設(shè)備性能消耗,PeriodicWorkRequest.Builder構(gòu)造函數(shù)中傳入的運(yùn)行周期間隔不能短于15分鐘,示例代碼如下:
PeriodicWorkRequest.Builder(SimpleWorker::class.java,15,TimeUnit.MINUTES).build()
最后一步,將構(gòu)建出來(lái)的后臺(tái)任務(wù)請(qǐng)求傳入WorkManager的enqueue()方法中,系統(tǒng)就會(huì)在合適的時(shí)間去運(yùn)行
WorkManager.getInstance(this).enqueue(request)
布局增加一個(gè)按鈕
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/doWorkBtn" android:layout_gravity="center_horizontal" android:text="Do Work" /> </LinearLayout>
修改MainActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
doWorkBtn.setOnClickListener {
val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java).build()
WorkManager.getInstance(this).enqueue(request)
}
}
}
點(diǎn)擊按鈕后,SimpleWorker打印日志
使用WorkManager處理復(fù)雜的任務(wù)
首先讓后臺(tái)任務(wù)在指定的延遲時(shí)間后運(yùn)行,只需要借助setInitialDelay()方法就可以了,代碼如下:
val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
.setInitialDelay(5,TimeUnit.MINUTES)
.build()
這就表示我們希望讓SimpleWorker這個(gè)后臺(tái)任務(wù)在5分鐘后運(yùn)行。
當(dāng)我們給后臺(tái)任務(wù)請(qǐng)求添加標(biāo)簽時(shí),可以這樣寫
val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
.addTag("simple")
.build()
添加標(biāo)簽最主要的一個(gè)功能就是通過(guò)標(biāo)簽取消后臺(tái)任務(wù)請(qǐng)求
WorkManager.getInstance(this).cancelAllWorkByTag("simple")
也可以通過(guò)id來(lái)取消后臺(tái)任務(wù)請(qǐng)求:
WorkManager.getInstance(this).cancelWorkById(request.id)
但是使用id只能取消單個(gè)后臺(tái)任務(wù)請(qǐng)求,而使用標(biāo)簽的話,則可以將同一標(biāo)簽名的所有后臺(tái)任務(wù)請(qǐng)求全部取消,這個(gè)功能在邏輯復(fù)雜的場(chǎng)景尤其有用。
除此之外,還可以使用如下代碼一次性取消所有后臺(tái)任務(wù)請(qǐng)求:
WorkManager.getInstance(this).cancelAllWork()
如果后臺(tái)任務(wù)的doWork()方法中返回了Result.retry()那么是可以結(jié)合setBackoffCriteria()方法來(lái)重新執(zhí)行任務(wù)的,具體代碼如下:
val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
.setBackoffCriteria(BackoffPolicy.LINEAR,10,TimeUnit.SECONDS)
.build()
setBackoffCriteria()方法接收3個(gè)參數(shù):第二個(gè)和第三個(gè)參數(shù)用于指定在多久之后重新執(zhí)行任務(wù),時(shí)間最短不能少于10秒鐘;第一個(gè)參數(shù)用于指定如果任務(wù)再次執(zhí)行失敗,下次重試的時(shí)間應(yīng)該以什么樣的形式延遲。第一個(gè)參數(shù)的可選值有兩種,分別是LINEAR和EXPONENTIAL,前者表示下次重試時(shí)間以線性的方式延遲,后者代表下次重試時(shí)間以指數(shù)的方式延遲。
而doWork()方法中返回的Result.success()和Result.failure()又有什么作用?這兩個(gè)返回值其實(shí)就是用于通知任務(wù)運(yùn)行結(jié)果的,我們可以使用如下代碼進(jìn)行監(jiān)聽(tīng):
WorkManager.getInstance(this).getWorkInfoByIdLiveData(request.id).
observe(this){
workInfo->
if(workInfo.state==WorkInfo.State.SUCCEEDED){
Log.d(TAG, "do work succeeded")
}else if(workInfo.state==WorkInfo.State.FAILED){
Log.d(TAG, "do work failed")
}
}
這里調(diào)用了getWorkInfoByIdLiveData()方法,并傳入后臺(tái)任務(wù)請(qǐng)求的id,會(huì)返回一個(gè)LiveData對(duì)象。然后我們就可以調(diào)用LiveData對(duì)象的observe()方法來(lái)觀察數(shù)據(jù)變化了,以監(jiān)聽(tīng)后臺(tái)任務(wù)的運(yùn)行結(jié)果。
另外,還可以調(diào)用getWorkInfoByTagLiveData()方法,監(jiān)聽(tīng)同一標(biāo)簽名下所有后臺(tái)任務(wù)請(qǐng)求的運(yùn)行結(jié)果。
WorkManager還有一個(gè)特色的功能—鏈?zhǔn)饺蝿?wù)
假設(shè)這里定義了3個(gè)獨(dú)立的后臺(tái)任務(wù):同步數(shù)據(jù)、壓縮數(shù)據(jù)和上傳數(shù)據(jù)。現(xiàn)在我們想要實(shí)現(xiàn)先同步、再壓縮、最后上傳的功能,就可以借助鏈?zhǔn)饺蝿?wù)來(lái)實(shí)現(xiàn),代碼示例如下:
val sync=...
val compress=...
val upload=...
WorkManager.getInstance(this)
.beginWith(sync)
.then(compress)
.them(upload)
.enqueue()
beginWith()方法用于開(kāi)啟一個(gè)鏈?zhǔn)饺蝿?wù),至于后面要接上什么樣的后臺(tái)任務(wù),只需要使用then()方法來(lái)連接即可。另外WorkManager還要求,必須在前一個(gè)后臺(tái)任務(wù)運(yùn)行成功之后,下一個(gè)后臺(tái)任務(wù)才會(huì)運(yùn)行。也就是說(shuō),如果某個(gè)后臺(tái)任務(wù)運(yùn)行失敗,或者被取消了,那么接下來(lái)的后臺(tái)任務(wù)就得不到運(yùn)行了。
原文鏈接:https://blog.csdn.net/ChenYiRan123456/article/details/128740405
相關(guān)推薦
- 2022-04-24 Pygame?Surface創(chuàng)建圖像的實(shí)現(xiàn)_python
- 2022-06-06 PyTorch?device與cuda.device用法介紹_python
- 2023-03-11 React中的for循環(huán)解讀_React
- 2022-08-13 Linux管理員root密碼忘記了怎么辦?
- 2022-12-27 React組件間通訊傳值實(shí)現(xiàn)詳解_React
- 2022-01-20 淺談關(guān)于 && , || , ? : , ?? , ?. 的運(yùn)算方式以及用法
- 2023-05-26 C#?using()的使用方法_C#教程
- 2022-09-30 C#?wpf?Canvas中實(shí)現(xiàn)控件拖動(dòng)調(diào)整大小的示例_C#教程
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支