Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WorkManager in Android 2——高级用法 #218

Open
soapgu opened this issue Aug 10, 2023 · 0 comments
Open

WorkManager in Android 2——高级用法 #218

soapgu opened this issue Aug 10, 2023 · 0 comments
Labels

Comments

@soapgu
Copy link
Owner

soapgu commented Aug 10, 2023

  • 前言

上面一个章节WorkManager in Android 1 —— 初见
简单介绍了WorkManager的功能,还没有学到令人激动的功能,没有感受到这个组件的好处
这一篇介绍下WorkManager的高级用法,可能更加具备实践性。

  • 加急工作

默认我们的WorkManager加入工作队列后并不是立即执行的,需要设置setExpedited才能立即执行,这种场景在一次性任务情况比较多,这里不展开

  • 调度定期工作

这个比较有用,调度定期任务,比如每天凌晨同步数据等场景
比较有意思的是,这里可以设置repeatInterval(重复时间),flexInterval(灵活间隔)。
图片
在flexInterval时间内执行,我并不关心他精确的周期执行情况

Sample

    @IntoMap
    @StringKey("update_token")
    @Provides
    public PeriodicWorkRequest providePeriodicWorkRequest(){
        return new PeriodicWorkRequest.Builder(TokenUpdateWork.class,
                20, TimeUnit.HOURS,
                1,TimeUnit.HOURS)
                .build();
    }

这里我的场景是更新客户端的token,由于是24小时会过期,我把周期设为20小时,这样token就不会过期。
flexInterval我设为1小时,1个小时内只要他执行了就行。

  • 重试和退避政策

说白了就是重试机制
和RxJava中的retryWhen很像

线性策略,也是默认值,比如Delay设为默认值10秒,怎么重试为10,20,30,40,有点对标物理对标“均加速直线运动”

指数策略,重试变为10、20、40、80 ,有点“变加速直线运动”的味道

至少重试机制WorkManager以及帮我搞定了,基本上用默认策略就行

  • 参数设置

可以通过WorkRequest的setInputData,格式和Intent的参数设置差别不大,Work部分可以通过getInputData获取

  • Unique Work(唯一工作)

唯一名称仅与一个工作实例相关联,这样就能保证当前运行只有这一个工作。因为很多时候工作多实例是没有意义的。可以理解为单例模式。

那么对于工作冲突重复怎么解决

  • existingWorkPolicy - 此 enum 可告知 WorkManager:如果已有使用该名称且尚未完成的唯一工作链,应执行什么操作。如需了解详情,请参阅冲突解决政策

  • CANCEL_AND_REENQUEUE

REPLACE,用新工作替换现有工作。此选项将取消现有工作

  • KEEP:保留现有工作,并忽略新工作

  • APPEND:将新工作附加到现有工作的末尾。此政策将导致您的新工作链接到现有工作,在现有工作完成后运行。

现有工作将成为新工作的先决条件。如果现有工作变为 CANCELLED 或 FAILED 状态,新工作也会变为 CANCELLED 或 FAILED。如果您希望无论现有工作的状态如何都运行新工作,请改用 APPEND_OR_REPLACE。

  • APPEND_OR_REPLACE 函数类似于 APPEND,不过它并不依赖于先决条件工作状态。即使现有工作变为 CANCELLED 或 FAILED 状态,新工作仍会运行。

后面两个选项暂时还没用过

  • 工作监控追踪

虽然Work对我们来说是黑盒,我们要做的就是定义好扔给系统就好了,系统会帮我们办好的。甩手掌柜式服务多好!
但是并不是说没法监控追踪任务执行了

支持Livedata,下面是例子

workManager.getWorkInfoByIdLiveData(syncWorker.id)
        .observe(getViewLifecycleOwner(), workInfo -> {
    if (workInfo.getState() != null &&
            workInfo.getState() == WorkInfo.State.SUCCEEDED) {
        Snackbar.make(requireView(),
                    R.string.work_completed, Snackbar.LENGTH_SHORT)
                .show();
   }
});
  • 观察任务中间过程

Work Manager支持在执行过程中发送数据,不仅仅进度哦,可以是自定义任何数据

数据发送

import android.content.Context;
import androidx.annotation.NonNull;
import androidx.work.Data;
import androidx.work.Worker;
import androidx.work.WorkerParameters;

public class ProgressWorker extends Worker {

    private static final String PROGRESS = "PROGRESS";
    private static final long DELAY = 1000L;

    public ProgressWorker(
        @NonNull Context context,
        @NonNull WorkerParameters parameters) {
        super(context, parameters);
        // Set initial progress to 0
        setProgressAsync(new Data.Builder().putInt(PROGRESS, 0).build());
    }

    @NonNull
    @Override
    public Result doWork() {
        try {
            // Doing work.
            Thread.sleep(DELAY);
        } catch (InterruptedException exception) {
            // ... handle exception
        }
        // Set progress to 100 after you are done doing your work.
        setProgressAsync(new Data.Builder().putInt(PROGRESS, 100).build());
        return Result.success();
    }
}

数据接收

WorkManager.getInstance(getApplicationContext())
     // requestId is the WorkRequest id
     .getWorkInfoByIdLiveData(requestId)
     .observe(lifecycleOwner, new Observer<WorkInfo>() {
             @Override
             public void onChanged(@Nullable WorkInfo workInfo) {
                 if (workInfo != null) {
                     Data progress = workInfo.getProgress();
                     int value = progress.getInt(PROGRESS, 0)
                     // Do something with progress
             }
      }
});

其实这对于耗时任务才有意义,暂时还用不到

  • 链接工作

如图
图片
工作被链接成了工作流
虽然很华丽,但是暂时还没实际的业务应用场景,还无法落地。大型的商用app可能有场景,这里只能先略了

  • 总结&预告

WorkManager这次学习到了很多“高级”功能,大大提升了实用性。

但是离实际还差两个要点

  • 怎么解决RxJava框架结合问题,至少快速入门的Worker和RxJava八字不合,难道我还要把RxJava拆成同步方法?
  • 怎么解决依赖注入,Worker并不属于Android的组件,Hilt框架似乎没有入口点。另外Worker也是一个相对封闭的类,运行过程也属于托管运行,没有办法过程中干预或者传入复杂依赖,似乎陷入困境了

好消息,问题已经得到了解决,至于怎么解决的。我将在WorkManager in Android 3中发布。敬请期待!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant