Android中WorkManager的簡單使用
1.簡介:
WorkManager:
WorkManager是Google推出的一個新組件,用于替代傳統(tǒng)的Service進(jìn)行后臺任務(wù)處理。它的主要特點(diǎn)包括:
獨(dú)立執(zhí)行:WorkManager的任務(wù)可以在應(yīng)用退出后繼續(xù)執(zhí)行,適用于需要延遲執(zhí)行或應(yīng)用退出后仍需運(yùn)行的任務(wù)。
靈活的觸發(fā)器:可以根據(jù)需要設(shè)置不同的觸發(fā)器,如定時任務(wù)、網(wǎng)絡(luò)狀態(tài)變化等。
自動管理:WorkManager會自動管理任務(wù)的執(zhí)行和重試,減少了開發(fā)者的工作量。
兼容性:WorkManager會根據(jù)設(shè)備的API情況自動選擇合適的實(shí)現(xiàn)方式,
2.核心概念:
在深入了解WorkManager之前,讓我們先了解一些核心概念:
WorkRequest(工作請求):表示要執(zhí)行的單個后臺任務(wù)。它包含任務(wù)的唯一標(biāo)識符、約束條件(如網(wǎng)絡(luò)連接、充電狀態(tài)等)以及其他配置選項(xiàng)。
Worker(工作者):執(zhí)行實(shí)際后臺任務(wù)的類。您可以擴(kuò)展Worker類并重寫doWork()方法來定義自己的后臺邏輯。
WorkManager(工作管理器):用于調(diào)度和跟蹤工作請求的中心類。它負(fù)責(zé)將工作請求提交給適當(dāng)?shù)暮笈_任務(wù)執(zhí)行器,并處理與工作周期、重試策略等相關(guān)的邏輯。
Constraints(約束條件):用于指定工作請求在何時運(yùn)行的條件,如網(wǎng)絡(luò)狀態(tài)、電池狀態(tài)等。
WorkInfo(工作信息):提供有關(guān)工作請求當(dāng)前狀態(tài)和結(jié)果的信息。
3.簡單任務(wù):
/**
* @auth: njb
* @date: 2024/11/26 23:14
* @desc: 簡單任務(wù)
*/
classMainWorker(context:Context,workerParams:WorkerParameters):Worker(context,workerParams) {
overridefundoWork():Result{
Log.e(Constants.TAG,"簡單任務(wù) 執(zhí)行完畢"+Result.success())
returnResult.success()
?? }
}
4.周期性任務(wù):
/**
* @auth: njb
* @date: 2024/11/26 23:34
* @desc: 周期性任務(wù)
*/
classPeriodicWork(context:Context,workerParams:WorkerParameters) :
Worker(context,workerParams) {
overridefundoWork():Result{
Log.e(Constants.TAG,"周期性任務(wù) 執(zhí)行完畢")
returnResult.success()
?? }
}
5.傳遞數(shù)據(jù):
packagecom.cloud.workmanagerdemo
importandroid.content.Context
importandroid.util.Log
importandroidx.work.Data
importandroidx.work.Worker
importandroidx.work.WorkerParameters
/**
* @auth: njb
* @date: 2024/11/26 23:38
* @desc: 傳達(dá)數(shù)據(jù)
*/
classTransferDataWork(context:Context,workerParams:WorkerParameters) :
Worker(context,workerParams) {
overridefundoWork():Result{
valactivityData=inputData.getString("data")
Log.e(Constants.TAG,"傳遞數(shù)據(jù)任務(wù) $activityData ")
valdata=Data.Builder()
.putString("data","TransferDataWork的數(shù)據(jù)").build()
returnResult.success(data)
?? }
}
6.任務(wù)鏈:
packagecom.cloud.workmanagerdemo
importandroid.content.Context
importandroid.util.Log
importandroidx.work.Worker
importandroidx.work.WorkerParameters
/**
* @auth: njb
* @date: 2024/11/26 23:38
* @desc: 任務(wù)鏈WorkManager
*/
classDisPatchWork(context:Context,workerParams:WorkerParameters) :
Worker(context,workerParams) {
overridefundoWork():Result{
valactivityData=inputData.getString("data")
Log.e(Constants.TAG,"任務(wù)鏈$activityData")
returnResult.success()
?? }
}
7.主界面代碼:
<?xmlversion="1.0"encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv_main"
android:layout_width="200dp"
android:layout_height="40dp"
android:text="簡單任務(wù)"
android:textColor="@color/white"
android:textSize="20sp"
android:onClick="mainWork"
android:gravity="center"
android:background="@color/design_default_color_primary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="100dp"/>
<TextView
android:id="@+id/tv_data"
android:layout_width="200dp"
android:layout_height="40dp"
android:text="傳遞數(shù)據(jù)"
android:onClick="transferDataWork"
android:textColor="@color/white"
android:textSize="20sp"
android:gravity="center"
android:layout_marginTop="20dp"
android:background="@color/design_default_color_primary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_main"/>
<TextView
android:id="@+id/tv_more"
android:layout_width="200dp"
android:layout_height="40dp"
android:text="任務(wù)鏈"
android:onClick="moreWork"
android:textColor="@color/white"
android:textSize="20sp"
android:gravity="center"
android:layout_marginTop="20dp"
android:background="@color/design_default_color_primary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_data"/>
<TextView
android:id="@+id/tv_poll"
android:layout_width="200dp"
android:layout_height="40dp"
android:text="周期性任務(wù)"
android:onClick="periodicTask"
android:textColor="@color/white"
android:textSize="20sp"
android:gravity="center"
android:layout_marginTop="20dp"
android:background="@color/design_default_color_primary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_more"/>
</androidx.constraintlayout.widget.ConstraintLayout>
8.測試代碼:
packagecom.cloud.workmanagerdemo
importandroid.os.Bundle
importandroid.util.Log
importandroid.view.View
importandroidx.appcompat.app.AppCompatActivity
importandroidx.work.Data
importandroidx.work.OneTimeWorkRequest;
importandroidx.work.PeriodicWorkRequest;
importandroidx.work.WorkManager;
importjava.util.concurrent.TimeUnit
classMainActivity:AppCompatActivity() {
overridefunonCreate(savedInstanceState:Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
?? }
funmainWork(view:View?) {
/* ? ? ? val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
val dateFormat = SimpleDateFormat("hh:mm:ss", Locale.getDefault())
val data = Data.Builder()
.putString("date", dateFormat.format(Date()))
.build()
val oneTimeWorkRequest = OneTimeWorkRequest
.Builder(MainWorker::class.java)
.setConstraints(constraints)
.setInputData(data)
.build()
WorkManager.getInstance(this@MainActivity).enqueue(oneTimeWorkRequest)
WorkManager.getInstance(this)
.getWorkInfoByIdLiveData(oneTimeWorkRequest.id)
.observe(this) { workInfo ->
workInfo?.let {
if(it.state.isFinished){
val outputData = workInfo.outputData
Log.e("傳遞數(shù)據(jù)任務(wù)", outputData.getString("data")!!)
}
}
}*/
valoneTimeWorkRequest:OneTimeWorkRequest=
OneTimeWorkRequest.Builder(MainWorker::class.java)
.setInitialDelay(2,TimeUnit.SECONDS)
.build()
WorkManager.getInstance(this).enqueue(oneTimeWorkRequest)
?? }
funtransferDataWork(view:View?) {
valdata=Data.Builder()
.putString("data","Activity的數(shù)據(jù)").build()
valoneTimeWorkRequest:OneTimeWorkRequest=OneTimeWorkRequest.Builder(TransferDataWork::class.java)
.setInputData(data)
.build()
WorkManager.getInstance(this).enqueue(oneTimeWorkRequest)
//監(jiān)聽Worker回傳的數(shù)據(jù)
WorkManager.getInstance(this)
.getWorkInfoByIdLiveData(oneTimeWorkRequest.id)
.observe(this) {value->
if(value.state.isFinished) {
valoutputData=value.outputData
Log.e("傳遞數(shù)據(jù)任務(wù)",outputData.getString("data")!!)
? ? ? ? ? ? ?? }
? ? ? ? ?? }
?? }
/**
* 任務(wù)鏈
* @param view
*/
funmoreWork(view:View?) {
valworkerRequests:ArrayList<OneTimeWorkRequest>=ArrayList()
//任務(wù)1
valoneTimeWorkRequest1:OneTimeWorkRequest=
OneTimeWorkRequest.Builder(DisPatchWork::class.java)
.setInputData(Data.Builder().putString("data","任務(wù)1").build())
.build()
//任務(wù)2
valoneTimeWorkRequest2:OneTimeWorkRequest=
OneTimeWorkRequest.Builder(DisPatchWork::class.java)
.setInputData(Data.Builder().putString("data","任務(wù)2").build())
.build()
workerRequests.add(oneTimeWorkRequest1)
workerRequests.add(oneTimeWorkRequest2)
//任務(wù)3
valoneTimeWorkRequest3:OneTimeWorkRequest=
OneTimeWorkRequest.Builder(DisPatchWork::class.java)
.setInputData(Data.Builder().putString("data","任務(wù)3").build())
.build()
WorkManager.getInstance(this)
.beginWith(workerRequests)//先執(zhí)行的任務(wù)
.then(oneTimeWorkRequest3)//后執(zhí)行的任務(wù)
.enqueue()
?? }
/**
* 周期性任務(wù)
* @param view
*/
funperiodicTask(view:View?) {
valperiodicWorkRequest:PeriodicWorkRequest=
PeriodicWorkRequest.Builder(PeriodicWork::class.java,15,TimeUnit.MINUTES)
.build()
WorkManager.getInstance(this)
.enqueue(periodicWorkRequest)
?? }
}
9.日志打?。?/p>
11.實(shí)現(xiàn)效果如下:
12.使用場景:
Service適用場景:適用于需要在應(yīng)用內(nèi)部持續(xù)運(yùn)行的后臺任務(wù),如音樂播放、數(shù)據(jù)上傳等。由于Service依賴于主線程,不適合進(jìn)行耗時的操作。
WorkManager適用場景:適用于需要延遲執(zhí)行或應(yīng)用退出后仍需運(yùn)行的任務(wù),如定時任務(wù)、數(shù)據(jù)同步等。WorkManager可以自動管理任務(wù)的執(zhí)行和重試,減少了開發(fā)者的負(fù)擔(dān)。
13.總結(jié):
Service和WorkManager各有優(yōu)缺點(diǎn),選擇使用哪一個取決于具體的需求場景。如果需要依賴應(yīng)用內(nèi)部運(yùn)行的后臺任務(wù),且任務(wù)不涉及耗時操作,可以選擇Service;如果需要延遲執(zhí)行或應(yīng)用退出后仍需運(yùn)行的任務(wù),且希望減少開發(fā)工作量,可以選擇WorkManager。
14.后臺任務(wù)選擇:
場景推薦
需系統(tǒng)觸發(fā),不必完成ThreadPool + Broadcast
需系統(tǒng)觸發(fā),必須完成,可推遲WorkManager
需系統(tǒng)觸發(fā),必須完成,立即ForegroundService + Broadcast
不需系統(tǒng)觸發(fā),不必完成ThreadPool
不需系統(tǒng)觸發(fā),必須完成,可推遲WorkManager
不需系統(tǒng)觸發(fā),必須完成,立即ForegroundService
15.項(xiàng)目demo代碼: