Android Jetpack:WorkManager使用教程

介绍

WorkManager是Android Jetpack的一个强大的组件,用于处理后台耗时任务。后台任务可以是一次性的,也可以是重复的。

快速入门

在使用前先把库导进来,其中前两个是必选项。

dependencies {
    def work_version = "2.7.1"
    // (Java only)
    implementation "androidx.work:work-runtime:$work_version"
    // Kotlin + coroutines
    implementation "androidx.work:work-runtime-ktx:$work_version"
    // optional - RxJava2 support
    implementation "androidx.work:work-rxjava2:$work_version"
    // optional - GCMNetworkManager support
    implementation "androidx.work:work-gcm:$work_version"
    // optional - Test helpers
    androidTestImplementation "androidx.work:work-testing:$work_version"
    // optional - Multiprocess support
    implementation "androidx.work:work-multiprocess:$work_version"
}

WorkManager使用非常简单,就是定义任务,设置请求,提交即可。我们先来定义一个后台任务。

任务类继承自Worker类,在doWork里完成耗时任务。

public class SensorWorker extends Worker {
    private String TAG = "SensorWorker";

    public SensorWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }

    @NonNull
    @Override
    public Result doWork() {
        Log.d(TAG, "work begin");
        try {
        	//模拟后台耗时任务
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        if(Math.random() < 0.5){
        	//任务出现异常,返回failure
        	Log.d(TAG, "work failed");
            return Result.failure();
        }
        
        //任务完成,返回success
        Log.d(TAG, "work succeed");
        return Result.success();
    }
}

接着设置一个任务请求,这里使用了建造者模式,也就是说我们是可以通过Builder来做更多具体的设定的。

WorkRequest request = new OneTimeWorkRequest.Builder(SensorWorker.class)
                .build();

如果希望任务延迟30分钟再执行,则代码如下。

WorkRequest request = new OneTimeWorkRequest.Builder(SensorWorker.class)
				.setInitialDelay(30, TimeUnit.MINUTES)
                .build();

最后提交请求即可,使用起来跟Retrofit和Glide非常像。

WorkManager.getInstance(this)
                .enqueue(request);

失败处理

我们并不能保证任务每次都一定完成,对于任务异常,可以选择直接返回failure或者重新执行任务。下面来看看重试的代码。

public class SensorWorker extends Worker {
    ...
    @NonNull
    @Override
    public Result doWork() {
        Log.d(TAG, "work begin");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        if(Math.random() < 0.5){
            //任务异常,重试
            return Result.retry();
        }

        return Result.success();
    }
}

接着配置一下重试的策略,下面规定任务异常后20秒后才重试。WorkManager规定最短间隔时间为10秒。

重试策略有两种。当然,重试的间隔时间并不是精确的,毕竟Android不是实时操作系统。

重试策略 解释
BackoffPolicy.LINEAR 重试间隔保持不变
BackoffPolicy.EXPONENTIAL 每次重试间隔是上一次的2倍
WorkRequest request = new OneTimeWorkRequest.Builder(SensorWorker.class)
                .setBackoffCriteria(BackoffPolicy.LINEAR,20, TimeUnit.SECONDS)
                .build();

周期性任务

WorkManager还支持执行周期性的任务。使用方法如下。最小间隔时间是15分钟。

WorkRequest request = new PeriodicWorkRequest.Builder(SensorWorker.class,1,TimeUnit.HOURS)
                .build();

或者

WorkRequest request2 = new PeriodicWorkRequest.Builder(SensorWorker.class,1,TimeUnit.HOURS,15,TimeUnit.MINUTES)
                .build();

任务约束

后台任务种类繁多,有的会消耗流量、有的非常耗电。对于后台任务WorkManager也有一些约束它们的方法。

Constraints类可以通过建造者模式来设置需要的限定条件,常用的限制条件如下。

方法 解释
setRequiredNetworkType 设置任务执行的网络类型
setRequiresCharging 是否需要在充电下执行
setRequiresBatteryNotLow 是否需要在非低电量下执行
setRequiresStorageNotLow 是否需要在磁盘充足时执行
Constraints constraints = new Constraints.Builder()
                .setRequiredNetworkType(NetworkType.UNMETERED)
                .setRequiresCharging(true)
                .setRequiresBatteryNotLow(true)
                .setRequiresStorageNotLow(true)
                .build();

WorkRequest request = new OneTimeWorkRequest.Builder(SensorWorker.class)
                .setConstraints(constraints)
                .build();

取消任务

WorkManager提供了一些取消任务的方法。需要注意的是WorkManager只能取消周期性任务,单次任务是无法取消的。测试方法如下。

public class MainActivity extends AppCompatActivity {

    private Button button;
    private UUID mTaskId;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = findViewById(R.id.button);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            	//通过Id来取消任务
                WorkManager.getInstance(MainActivity.this)
                        .cancelWorkById(mTaskId);
            }
        });

        //注意,WorkManager只能取消周期性任务
        WorkRequest request = new PeriodicWorkRequest.Builder(SensorWorker.class,30,TimeUnit.MINUTES)
                .build();
		
		//获取任务的Id
        mTaskId = request.getId();

        WorkManager.getInstance(this)
                .enqueue(request);
    }
}

任务监听

我们还可以给任务添加监听器,这样一来就可以在不同任务状态下更新相应的UI了,代码如下。onChanged方法是在主线程下调用的,所以可以直接刷新UI。

//添加任务监听
        WorkManager.getInstance(MainActivity.this).getWorkInfoByIdLiveData(mTaskId).observe(this, new Observer<WorkInfo>() {
            @Override
            public void onChanged(WorkInfo workInfo) {
                if(workInfo.getState() != null && workInfo.getState() == WorkInfo.State.SUCCEEDED){
                    Toast.makeText(MainActivity.this, "finished", Toast.LENGTH_SHORT).show();
                }
            }
        });

最后

本篇文章讲解了Jetpack的处理后台任务的强大组件WorkManager。

参考文章

《WorkManager (3) —— 取消和监听任务》
《Android 开发者文档》

你可能感兴趣的:(Jetpack,android,jetpack,kotlin,android)