【Android-Jetpack进阶】6、WorkManager 后台线程、一次性、周期性、任务链的 Work

六、WorkManager 后台线程

WorkManager 用于 App 中不需要及时完成的任务(如上报日志、同步数据),因为将任务落盘到数据库故其保证即使设备重启、App 彻底退出,都依然会执行,其省电,兼容几乎所有设备(高版本用 JobScheduler,低版本用 AlarmManager,最终都是用 Adnroid 的 Executor 执行的),架构如下图。

在这里插入图片描述

首先,新建项目,项目github地址详见,在 build.gradle(app) 添加如下依赖:

    def work_version = "2.7.1"
    implementation "androidx.work:work-runtime-ktx:$work_version"

然后,新建UploadLogWorker 类,负责上报日志,代码如下:

package com.bignerdranch.android.jetpack6workmanagertest

import android.content.Context
import android.util.Log
import androidx.work.Data
import androidx.work.Worker
import androidx.work.WorkerParameters


// 上传日志的Worker
class UploadLogWorker(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) {
    
    
    /**
     * 耗时的任务,在doWork()方法中执行
     *
     * 执行成功返回Result.success()
     * 执行失败返回Result.failure()
     * 需要重新执行返回Result.retry()
     */
    override fun doWork(): Result {
    
    
        //接收外面传递进来的数据
        val inputData: String? = inputData.getString("input_data")
        Log.e("UploadLogWorker", "doWork()->get inputData:$inputData")

        // 任务执行完成后返回数据
        val outputData: Data = Data.Builder().putString("output_data", "Task Success!").build()
        return Result.success(outputData)
    }
}

新建 CompressLogWorker,表示任务成功运行,代码如下:

class CompressLogWorker(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) {
    
    
    /**
     * 耗时的任务,在doWork()方法中执行
     *
     * 执行成功返回Result.success()
     * 执行失败返回Result.failure()
     * 需要重新执行返回Result.retry()
     */
    override fun doWork(): Result {
    
    
        Log.e("CompressLogWorker", "doWork()")
        return Result.success()
    }
}

6.1 用 WorkRequest 配置任务的运行时机、方式

  • 设置任务触发条件
    例如当设备充电、已联网、电量充足时,触发任务,代码如下:
        val constraints: Constraints = Constraints.Builder()
            .setRequiresCharging(true)
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .setRequiresBatteryNotLow(true)
            .build()
  • 将任务触发条件、延迟执行,指数退避策略、标签,设置到 WorkRequest
        val uploadWorkRequest = OneTimeWorkRequest.Builder(UploadLogWorker::class.java)
            .setConstraints(constraints)//设置触发条件
            .setInitialDelay(10, TimeUnit.SECONDS) // 符合触发条件后,延迟10秒执行
            .setBackoffCriteria(BackoffPolicy.LINEAR, OneTimeWorkRequest.MIN_BACKOFF_MILLIS, TimeUnit.MILLISECONDS) //设置指数退避算法
            .setInputData(inputData)
            .addTag("UploadTag")
            .build()

通过 WorkManager.getWorkInfosByTag() 可得到 WorkInfo 对象,通过 WorkManager.getWorkInfosByTagLiveData() 可监听任务状态变化,通过 cancelAllWork() 可取消所有任务,

6.2 一次性、周期性、任务链的 Work

完整的 MainActivity 代码如下:

package com.bignerdranch.android.jetpack6workmanagertest

import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.work.*
import java.util.concurrent.TimeUnit


class MainActivity : AppCompatActivity() {
    
    
    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        startOneTimeTask()
        // startPeriodicWorkRequest();
        // startChainTask();
    }

    // 开启一个一次性任务
    private fun startOneTimeTask() {
    
    
        val constraints: Constraints = Constraints.Builder()
            .setRequiresCharging(true)
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .setRequiresBatteryNotLow(true)
            .build()
        val inputData: Data = Data.Builder().putString("input_data", "Hello World!").build()
        val uploadWorkRequest = OneTimeWorkRequest.Builder(UploadLogWorker::class.java)
            .setConstraints(constraints)//设置触发条件
            .setInitialDelay(10, TimeUnit.SECONDS) // 符合触发条件后,延迟10秒执行
            .setBackoffCriteria(BackoffPolicy.LINEAR, OneTimeWorkRequest.MIN_BACKOFF_MILLIS, TimeUnit.MILLISECONDS) //设置指数退避算法
            .setInputData(inputData)
            .addTag("UploadTag")
            .build()
        WorkManager.getInstance(this).enqueue(uploadWorkRequest)
        //实时监听变化
        WorkManager.getInstance(this).getWorkInfoByIdLiveData(uploadWorkRequest.id).observe(this@MainActivity) {
    
     workInfo ->
            Log.d("onChanged()->", "workInfo:$workInfo")
            if (workInfo != null && workInfo.state == WorkInfo.State.SUCCEEDED) {
    
    
                val outputData = workInfo.outputData.getString("output_data")
                Log.d("onChanged()->", "doWork()->get outputData:$outputData")
                Toast.makeText(this@MainActivity, "Success!", Toast.LENGTH_LONG).show()
            }
        }
    }

    private val TAG = "PeriodicTask"

    /**
     * 开启一个定期任务
     *
     * 通过设置TAG的方式来监听任务状态的变化,也可以使用ID的方式来监听
     */
    private fun startPeriodicWorkRequest() {
    
    
        val constraints: Constraints = Constraints.Builder()
            .setRequiresCharging(true)
            .build()

        //不能少于15分钟
        val uploadWorkRequest = PeriodicWorkRequest.Builder(UploadLogWorker::class.java, 15, TimeUnit.MINUTES)
            .setConstraints(constraints) //设置触发条件
            .addTag(TAG)
            .build()
        WorkManager.getInstance(this).enqueue(uploadWorkRequest)
        WorkManager.getInstance(this).getWorkInfosByTagLiveData(TAG)
            .observe(this@MainActivity) {
    
     workInfos -> Log.d("onChanged()->", "workInfo:" + workInfos!![0]) }
    }

    /**
     * 取消任务
     */
    private fun cancelAllWork() {
    
    
        WorkManager.getInstance(this@MainActivity).cancelAllWork()
    }

    /**
     * 开启任务链,任务的执行具有先后顺序
     */
    private fun startChainTask() {
    
    
        val constraints: Constraints = Constraints.Builder()
            .setRequiresCharging(true)
            .build()
        val compressWorkRequest = OneTimeWorkRequest.Builder(CompressLogWorker::class.java)
            .setConstraints(constraints) //设置触发条件
            .setInitialDelay(10, TimeUnit.SECONDS) //符合触发条件后,延迟10秒执行
            .build()
        val uploadWorkRequest = OneTimeWorkRequest.Builder(UploadLogWorker::class.java)
            .setConstraints(constraints) //设置触发条件
            .setInitialDelay(10, TimeUnit.SECONDS) //符合触发条件后,延迟10秒执行
            .build()

        //实时监听变化
        WorkManager.getInstance(this).getWorkInfoByIdLiveData(uploadWorkRequest.id)
            .observe(this@MainActivity) {
    
     workInfo -> Log.d("onChanged()->", "workInfo:$workInfo") }
    }
}

运行后,打印日志如下,说明监听到了任务状态的变化:

2022-09-28 15:54:48.643 11533-11533/com.bignerdranch.android.jetpack6workmanagertest D/onChanged()->: workInfo:WorkInfo{
    
    mId='34e59f1e-3bd7-4ec7-9d4c-974dd314e1a9', mState=ENQUEUED, mOutputData=Data {
    
    }, mTags=[com.bignerdranch.android.jetpack6workmanagertest.UploadLogWorker, UploadTag], mProgress=Data {
    
    }}

猜你喜欢

转载自blog.csdn.net/jiaoyangwm/article/details/127088443