Android中WorkManager的简单使用
1.简介:
WorkManager:
WorkManager是Google推出的一个新组件,用于替代传统的Service进行后台任务处理。它的主要特点包括:
独立执行:WorkManager的任务可以在应用退出后继续执行,适用于需要延迟执行或应用退出后仍需运行的任务。
灵活的触发器:可以根据需要设置不同的触发器,如定时任务、网络状态变化等。
自动管理:WorkManager会自动管理任务的执行和重试,减少了开发者的工作量。
兼容性:WorkManager会根据设备的API情况自动选择合适的实现方式,
2.核心概念:
在深入了解WorkManager之前,让我们先了解一些核心概念:
WorkRequest(工作请求):表示要执行的单个后台任务。它包含任务的唯一标识符、约束条件(如网络连接、充电状态等)以及其他配置选项。
Worker(工作者):执行实际后台任务的类。您可以扩展Worker类并重写doWork()方法来定义自己的后台逻辑。
WorkManager(工作管理器):用于调度和跟踪工作请求的中心类。它负责将工作请求提交给适当的后台任务执行器,并处理与工作周期、重试策略等相关的逻辑。
Constraints(约束条件):用于指定工作请求在何时运行的条件,如网络状态、电池状态等。
WorkInfo(工作信息):提供有关工作请求当前状态和结果的信息。
3.简单任务:
/**
* @auth: njb
* @date: 2024/11/26 23:14
* @desc: 简单任务
*/
classMainWorker(context:Context,workerParams:WorkerParameters):Worker(context,workerParams) {
overridefundoWork():Result{
Log.e(Constants.TAG,"简单任务 执行完毕"+Result.success())
returnResult.success()
}
}
4.周期性任务:
/**
* @auth: njb
* @date: 2024/11/26 23:34
* @desc: 周期性任务
*/
classPeriodicWork(context:Context,workerParams:WorkerParameters) :
Worker(context,workerParams) {
overridefundoWork():Result{
Log.e(Constants.TAG,"周期性任务 执行完毕")
returnResult.success()
}
}
5.传递数据:
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: 传达数据
*/
classTransferDataWork(context:Context,workerParams:WorkerParameters) :
Worker(context,workerParams) {
overridefundoWork():Result{
valactivityData=inputData.getString("data")
Log.e(Constants.TAG,"传递数据任务 $activityData ")
valdata=Data.Builder()
.putString("data","TransferDataWork的数据").build()
returnResult.success(data)
}
}
6.任务链:
packagecom.cloud.workmanagerdemo
importandroid.content.Context
importandroid.util.Log
importandroidx.work.Worker
importandroidx.work.WorkerParameters
/**
* @auth: njb
* @date: 2024/11/26 23:38
* @desc: 任务链WorkManager
*/
classDisPatchWork(context:Context,workerParams:WorkerParameters) :
Worker(context,workerParams) {
overridefundoWork():Result{
valactivityData=inputData.getString("data")
Log.e(Constants.TAG,"任务链$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="简单任务"
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="传递数据"
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="任务链"
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="周期性任务"
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("传递数据任务", 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的数据").build()
valoneTimeWorkRequest:OneTimeWorkRequest=OneTimeWorkRequest.Builder(TransferDataWork::class.java)
.setInputData(data)
.build()
WorkManager.getInstance(this).enqueue(oneTimeWorkRequest)
//监听Worker回传的数据
WorkManager.getInstance(this)
.getWorkInfoByIdLiveData(oneTimeWorkRequest.id)
.observe(this) {value->
if(value.state.isFinished) {
valoutputData=value.outputData
Log.e("传递数据任务",outputData.getString("data")!!)
}
}
}
/**
* 任务链
* @param view
*/
funmoreWork(view:View?) {
valworkerRequests:ArrayList<OneTimeWorkRequest>=ArrayList()
//任务1
valoneTimeWorkRequest1:OneTimeWorkRequest=
OneTimeWorkRequest.Builder(DisPatchWork::class.java)
.setInputData(Data.Builder().putString("data","任务1").build())
.build()
//任务2
valoneTimeWorkRequest2:OneTimeWorkRequest=
OneTimeWorkRequest.Builder(DisPatchWork::class.java)
.setInputData(Data.Builder().putString("data","任务2").build())
.build()
workerRequests.add(oneTimeWorkRequest1)
workerRequests.add(oneTimeWorkRequest2)
//任务3
valoneTimeWorkRequest3:OneTimeWorkRequest=
OneTimeWorkRequest.Builder(DisPatchWork::class.java)
.setInputData(Data.Builder().putString("data","任务3").build())
.build()
WorkManager.getInstance(this)
.beginWith(workerRequests)//先执行的任务
.then(oneTimeWorkRequest3)//后执行的任务
.enqueue()
}
/**
* 周期性任务
* @param view
*/
funperiodicTask(view:View?) {
valperiodicWorkRequest:PeriodicWorkRequest=
PeriodicWorkRequest.Builder(PeriodicWork::class.java,15,TimeUnit.MINUTES)
.build()
WorkManager.getInstance(this)
.enqueue(periodicWorkRequest)
}
}
9.日志打印:
11.实现效果如下:
12.使用场景:
Service适用场景:适用于需要在应用内部持续运行的后台任务,如音乐播放、数据上传等。由于Service依赖于主线程,不适合进行耗时的操作。
WorkManager适用场景:适用于需要延迟执行或应用退出后仍需运行的任务,如定时任务、数据同步等。WorkManager可以自动管理任务的执行和重试,减少了开发者的负担。
13.总结:
Service和WorkManager各有优缺点,选择使用哪一个取决于具体的需求场景。如果需要依赖应用内部运行的后台任务,且任务不涉及耗时操作,可以选择Service;如果需要延迟执行或应用退出后仍需运行的任务,且希望减少开发工作量,可以选择WorkManager。
14.后台任务选择:
场景推荐
需系统触发,不必完成ThreadPool + Broadcast
需系统触发,必须完成,可推迟WorkManager
需系统触发,必须完成,立即ForegroundService + Broadcast
不需系统触发,不必完成ThreadPool
不需系统触发,必须完成,可推迟WorkManager
不需系统触发,必须完成,立即ForegroundService
15.项目demo代码: