Android WorkManager實(shí)現(xiàn)后臺定時任務(wù)流程詳解
WorkManager和Service并不相同,也沒有直接的聯(lián)系。Service是Android系統(tǒng)四大組件之一,它沒有被銷毀的情況下是一直保持在后臺運(yùn)行的。而WorkManager只是一個處理定時任務(wù)的工具,它可以保證即使在應(yīng)用退出甚至手機(jī)重啟的情況下,之前注冊的任務(wù)仍然將會得到執(zhí)行,因此WorkManager很適合用于執(zhí)行一些定期和服務(wù)器進(jìn)行交互的任務(wù),比如周期性地同步數(shù)據(jù)等等。
使用WorkManager注冊的周期性任務(wù)不能保證一定會準(zhǔn)時執(zhí)行,這是因?yàn)橄到y(tǒng)為了減少電量消耗,可能會將觸發(fā)時間臨近的幾個任務(wù)放在一起執(zhí)行,這樣可以大幅度減少CPU被喚醒的次數(shù),從而有效延長電池的使用時間。
WorkManager的基本用法
先添加依賴
implementation 'androidx.work:work-runtime-ktx:2.2.0'
WorkManager的基本用法主要分為以下3步:
- 定義一個后臺任務(wù),并實(shí)現(xiàn)具體的任務(wù)邏輯
- 配置該后臺任務(wù)的運(yùn)行條件和約束信息,并構(gòu)建后臺任務(wù)請求
- 將該后臺任務(wù)請求傳入WorkManager的enqueue()方法中,系統(tǒng)會在合適的時間運(yùn)行
第一步定義一個后臺任務(wù),這里創(chuàng)建一個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() } }
首先每一個后臺任務(wù)都必須繼承自Worker類,并調(diào)用它唯一的構(gòu)造函數(shù)。然后重寫父類中的doWork()方法,在這個方法中編寫具體的后臺任務(wù)邏輯。
第二步配置該后臺任務(wù)的運(yùn)行條件和約束信息
val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java).build()
可以看到,只需要把剛才創(chuàng)建的后臺任務(wù)所對應(yīng)的Class對象傳入 OneTimeWorkRequest.Builder的構(gòu)造函數(shù)當(dāng)中,然后調(diào)用build()方法就可以完成構(gòu)建。
OneTimeWorkRequest.Builder是WorkRequest.Builder的子類,用于構(gòu)建單次運(yùn)行的后臺任務(wù)請求。WorkRequest.Builder還有另外一個子類PeriodicWorkRequest.Builder,可用于構(gòu)建周期性運(yùn)行的后臺任務(wù)請求,但是為了降低設(shè)備性能消耗,PeriodicWorkRequest.Builder構(gòu)造函數(shù)中傳入的運(yùn)行周期間隔不能短于15分鐘,示例代碼如下:
PeriodicWorkRequest.Builder(SimpleWorker::class.java,15,TimeUnit.MINUTES).build()
最后一步,將構(gòu)建出來的后臺任務(wù)請求傳入WorkManager的enqueue()方法中,系統(tǒng)就會在合適的時間去運(yùn)行
WorkManager.getInstance(this).enqueue(request)
布局增加一個按鈕
<?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ù)
首先讓后臺任務(wù)在指定的延遲時間后運(yùn)行,只需要借助setInitialDelay()方法就可以了,代碼如下:
val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java) .setInitialDelay(5,TimeUnit.MINUTES) .build()
這就表示我們希望讓SimpleWorker這個后臺任務(wù)在5分鐘后運(yùn)行。
當(dāng)我們給后臺任務(wù)請求添加標(biāo)簽時,可以這樣寫
val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java) .addTag("simple") .build()
添加標(biāo)簽最主要的一個功能就是通過標(biāo)簽取消后臺任務(wù)請求
WorkManager.getInstance(this).cancelAllWorkByTag("simple")
也可以通過id來取消后臺任務(wù)請求:
WorkManager.getInstance(this).cancelWorkById(request.id)
但是使用id只能取消單個后臺任務(wù)請求,而使用標(biāo)簽的話,則可以將同一標(biāo)簽名的所有后臺任務(wù)請求全部取消,這個功能在邏輯復(fù)雜的場景尤其有用。
除此之外,還可以使用如下代碼一次性取消所有后臺任務(wù)請求:
WorkManager.getInstance(this).cancelAllWork()
如果后臺任務(wù)的doWork()方法中返回了Result.retry()那么是可以結(jié)合setBackoffCriteria()方法來重新執(zhí)行任務(wù)的,具體代碼如下:
val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java) .setBackoffCriteria(BackoffPolicy.LINEAR,10,TimeUnit.SECONDS) .build()
setBackoffCriteria()方法接收3個參數(shù):第二個和第三個參數(shù)用于指定在多久之后重新執(zhí)行任務(wù),時間最短不能少于10秒鐘;第一個參數(shù)用于指定如果任務(wù)再次執(zhí)行失敗,下次重試的時間應(yīng)該以什么樣的形式延遲。第一個參數(shù)的可選值有兩種,分別是LINEAR和EXPONENTIAL,前者表示下次重試時間以線性的方式延遲,后者代表下次重試時間以指數(shù)的方式延遲。
而doWork()方法中返回的Result.success()和Result.failure()又有什么作用?這兩個返回值其實(shí)就是用于通知任務(wù)運(yùn)行結(jié)果的,我們可以使用如下代碼進(jìn)行監(jiān)聽:
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()方法,并傳入后臺任務(wù)請求的id,會返回一個LiveData對象。然后我們就可以調(diào)用LiveData對象的observe()方法來觀察數(shù)據(jù)變化了,以監(jiān)聽后臺任務(wù)的運(yùn)行結(jié)果。
另外,還可以調(diào)用getWorkInfoByTagLiveData()方法,監(jiān)聽同一標(biāo)簽名下所有后臺任務(wù)請求的運(yùn)行結(jié)果。
WorkManager還有一個特色的功能—鏈?zhǔn)饺蝿?wù)
假設(shè)這里定義了3個獨(dú)立的后臺任務(wù):同步數(shù)據(jù)、壓縮數(shù)據(jù)和上傳數(shù)據(jù)?,F(xiàn)在我們想要實(shí)現(xiàn)先同步、再壓縮、最后上傳的功能,就可以借助鏈?zhǔn)饺蝿?wù)來實(shí)現(xiàn),代碼示例如下:
val sync=... val compress=... val upload=... WorkManager.getInstance(this) .beginWith(sync) .then(compress) .them(upload) .enqueue()
beginWith()方法用于開啟一個鏈?zhǔn)饺蝿?wù),至于后面要接上什么樣的后臺任務(wù),只需要使用then()方法來連接即可。另外WorkManager還要求,必須在前一個后臺任務(wù)運(yùn)行成功之后,下一個后臺任務(wù)才會運(yùn)行。也就是說,如果某個后臺任務(wù)運(yùn)行失敗,或者被取消了,那么接下來的后臺任務(wù)就得不到運(yùn)行了。
到此這篇關(guān)于Android WorkManager實(shí)現(xiàn)后臺定時任務(wù)流程詳解的文章就介紹到這了,更多相關(guān)Android WorkManager內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android如何使用Bmob后端云實(shí)現(xiàn)失物招領(lǐng)功能
這篇文章主要介紹了Android如何使用Bmob后端云實(shí)現(xiàn)失物招領(lǐng)功能,幫助大家更好的理解和學(xué)習(xí)使用Android,感興趣的朋友可以了解下2021-03-03詳解Androidstudio3.0 關(guān)于Gradle報錯的問題(小結(jié))
本篇文章主要介紹了詳解Androidstudio3.0 關(guān)于Gradle報錯的問題(小結(jié)),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-10-10Android自定義View實(shí)現(xiàn)等級滑動條的實(shí)例
這篇文章主要介紹了 Android自定義View實(shí)現(xiàn)等級滑動條的實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-04-04Android實(shí)現(xiàn)完整游戲循環(huán)的方法
這篇文章主要介紹了Android實(shí)現(xiàn)完整游戲循環(huán)的方法,以實(shí)例代碼形式較為詳細(xì)的分析了Android游戲循環(huán)的實(shí)現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-10-10Android實(shí)現(xiàn)Bitmap位圖旋轉(zhuǎn)效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)Bitmap位圖旋轉(zhuǎn)效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04android中Intent傳值與Bundle傳值的區(qū)別詳解
本篇文章是對android中Intent傳值與Bundle傳值的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05Android Listview notifyDataSetChanged() 不起作用的
這篇文章主要介紹了Android Listview notifyDataSetChanged()不起作用的解決方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2024-08-08Android編程實(shí)現(xiàn)微信分享信息的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)微信分享信息的方法,實(shí)例分析了Android官方demo示例,講述了Android微信分享功能的具體實(shí)現(xiàn)技巧,需要的朋友可以參考下2015-10-10