Android架构组件-WorkManager,【2024Android最新学习路线】

// Create a Constraints that defines when the task should run
Constraints myConstraints = new Constraints.Builder()
.setRequiresDeviceIdle(true)
.setRequiresCharging(true)
// Many other constraints are available, see the
// Constraints.Builder reference
.build();

// …then create a OneTimeWorkRequest that uses those constraints
OneTimeWorkRequest compressionWork = new OneTimeWorkRequest.Builder(CompressWorker.class)
.setConstraints(myConstraints)
.build();

然后像之前代码一样将新的OneTimeWorkRequest对象传递给WorkManager.enqueue()WorkManager在查找运行任务的时间时会考虑我们的约束条件。

取消任务

当我们将任务入列后,我们还可以取消这个任务。要取消任务,我们需要这个任务的Work ID,当然Work ID可以从WorkRequest对象中获取。例如,以下代码将取消上一节中的compressionWork请求:

UUID compressionWorkId = compressionWork.getId();
WorkManager.getInstance().cancelByWorkId(compressionWorkId);

WorkManager 会尽最大努力取消任务,但实质上这是不确定的 - 当我们尝试取消任务时,任务可能已经运行或完成。WorkManager还提供方法来取消 **唯一工作序列(这个概念在下面会讲到)**中的所有任务,或尽最大努力的取消具有指定标记的所有任务。

高级功能


WorkManager API 的核心功能可以使开发者能够创建简单的、即开即忘的任务,除此之外,API 还提供了高级功能,可以让我们设置更多精准的请求。

重复执行的任务

我们可能需要重复执行一项任务,例如,照片管理应用不会只想压缩其照片一次。更有可能的是,它会希望每隔一段时间检查一次照片,并查看是否有任何新的或改变的图像需要压缩,这个循环任务可以压缩它找到的图像,或者它可以启动新的“压缩图像”任务。

要创建循环任务,要使用PeriodicWorkRequest.Builder类创建一个PeriodicWorkRequest对象,然后将PeriodicWorkRequest以与OneTimeWorkRequest对象相同的方式入列。例如,假如我们定义了一个PhotoCheckWorker类来识别需要压缩的图像,如果我们想每12小时运行一次这个任务,我们可以像下面这样创建一个PeriodicWorkRequest对象 :

new PeriodicWorkRequest.Builder photoWorkBuilder =
new PeriodicWorkRequest.Builder(PhotoCheckWorker.class, 12,
TimeUnit.HOURS);
// …if you want, you can apply constraints to the builder here…

// Create the actual work object:
PeriodicWorkRequest photoWork = photoWorkBuilder.build();
// Then enqueue the recurring task:
WorkManager.getInstance().enqueue(invWork);

WorkManager 尝试按照我们请求的时间间隔运行任务,但要受到我们施加的限制和其他要求的限制。

链式任务

有时候我们想让应用程序按照特定的顺序运行多个任务。 WorkManager允许我们创建和排队多个任务的工作序列,以及它们应该以什么顺序运行。

例如,假如我们的应用有三个 OneTimeWorkRequest 对象:workA, workB, 和 workC,这些任务必须按照该顺序执行。要想将它们排队,请使用WorkManager.beginWith() 方法创建一个序列,并传递第一个OneTimeWorkRequest对象,该方法返回一个WorkContinuation对象,该对象定义了一系列任务。然后依次使用 WorkContinuation.then()添加剩余的OneTimeWorkRequest对象,最后使用 WorkContinuation.enqueue()排序整个序列:

WorkManager.getInstance()
.beginWith(workA)
// Note: WorkManager.beginWith() returns a
// WorkContinuation object; the following calls are
// to WorkContinuation methods
.then(workB) // FYI, then() returns a new WorkContinuation instance
.then(workC)
.enqueue();

WorkManager根据每个任务的指定约束以请求的顺序运行任务,如果任何任务返回Worker.WorkerResult.FAILURE,则整个序列结束。

我们还可以将多个OneTimeWorkRequest对象传递给beginWith().then() 调用中的任何一个。如果我们将多个OneTimeWorkRequest对象传递给单个方法调用,那么WorkManager将在运行序列中其余部分任务前运行所有这些任务(并行)。例如:

WorkManager.getInstance()
// First, run all the A tasks (in parallel):
.beginWith(workA1, workA2, workA3)
// …when all A tasks are finished, run the single B task:
.then(workB)
// …then run the C tasks (in any order):
.then(workC1, workC2)
.enqueue();

我们可以通过使用WorkContinuation.combine()方法连接多个链来创建更复杂的序列。例如,假设我们想要像下图运行一个序列:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图1.使用WorkContinuation来设置复杂的链式任务。

要建立这个序列,先创建两个单独的链,然后将它们连接在一起成为第三个链:

WorkContinuation chain1 = WorkManager.getInstance()
.beginWith(workA)
.then(workB);
WorkContinuation chain2 = WorkManager.getInstance()
.beginWith(workC)
.then(workD);
WorkContinuation chain3 = WorkContinuation
.combine(chain1, chain2)
.then(workE);
chain3.enqueue();

在这种情况下,WorkManagerworkB之前运行workA,它也在workD之前运行workCWorkBworkD都完成后,WorkManager 运行workE

注意:虽然WorkManager依次运行每个子链,但不能保证链1中的任务与 链2中的任务重叠,例如,workB可能在workC之前或之后运行,或者它们可能同时运行。唯一可以保证的是每个子链中的任务将按顺序运行,也就是说,workBworkA完成之后才开始。

WorkContinuation的方法有许多变体,可以为特定情况提供简要说明。例如,有一个WorkContinuation.combine(OneTimeWorkRequest, WorkContinuation…)方法,该方法指示 WorkManager完成所有指定的 WorkContinuation链,然后完成指定的OneTimeWorkRequest

唯一的工作序列

我们要想创建一个唯一的工作序列,只需调用beginUniqueWork()而不是 beginWith().来开始序列。每个唯一的工作序列都有一个名字,WorkManager一次只允许一个工作序列使用该名称,当我们创建一个新的唯一工作序列时,如果已经有一个未完成的序列具有相同的名称,则指定WorkManager应执行的操作:

  • 取消现有的序列并用新序列其替换
  • 保持现有顺序并忽略新的请求
  • 将新序列附加到现有序列,在现有序列的最后一个任务完成后运行新序列的第一个任务

如果我们有一个不应该多次入队的任务,则唯一工作序列可能很有用。例如,如果我们的应用需要将其数据同步到网络,我们可能会排列一个名为“sync”的序列,并指定如果已经有一个具有该名称的序列,则应该忽略我们的新任务。如果我们需要逐步建立一个长期的任务链,那么唯一的工作序列也会很有用,例如,照片编辑应用可能会让用户撤消一长串的操作,每个撤销操作可能需要一段时间,但必须按正确的顺序执行,在这种情况下,应用程序可以创建一个**“撤消”链**并根据需要将每个撤销操作追加到链中。

标记Work

我们可以通过将字符串标签指派给任何WorkRequest对象,将我们的任务按照逻辑分组。要设置标签,请调用WorkRequest.Builder.addTag(),例如:

OneTimeWorkRequest cacheCleanupTask =
new OneTimeWorkRequest.Builder(MyCacheCleanupWorker.class)
.setConstraints(myConstraints)
.addTag(“cleanup”)
.build();

WorkManager类提供了几种实用方法,可让我们使用特定标记对所有任务进行操作。例如,WorkManager.cancelAllWorkByTag()可以取消具有特定标记的所有任务,并且 WorkManager.getStatusesByTag()返回具有该标记的所有任务的所有WorkStatus的列表。

输入参数和返回值

为了获得更大的灵活性,还可以将参数传递给我们的任务,并让任务返回结果。传递和返回值都是键值对,要将参数传递给任务,在创建WorkRequest对象之前调用WorkRequest.Builder.setInputData()方法,该方法使用 Data.Builder创建的Data对象。 Worker类可以通过调用Worker.getInputData()来访问这些参数。要输出一个返回值,任务可以调用带有 Data对象的Worker.setOutputData(),我们可以通过观察任务的LiveData<WorkStatus>来获取输出。

例如,假设我们有一个执行耗时计算的Worker类,Worker类类似于下面的代码:

// Define the Worker class:
public class MathWorker extends Worker {

// Define the parameter keys:
public static final String KEY_X_ARG = “X”;
public static final String KEY_Y_ARG = “Y”;
public static final String KEY_Z_ARG = “Z”;
// …and the result key:
public static final String KEY_RESULT = “result”;

@Override
public Worker.WorkerResult doWork() {

// Fetch the arguments (and specify default values):
int x = getInputData().getInt(KEY_X_ARG, 0);
int y = getInputData().getInt(KEY_Y_ARG, 0);
int z = getInputData().getInt(KEY_Z_ARG, 0);

// …do the math…
int result = myCrazyMathFunction(x, y, z);

//…set the output, and we’re done!
Data output = new Data.Builder()
.putInt(KEY_RESULT, result)
.build();
setOutputData(output);
return WorkerResult.SUCCESS;
}
}

要创建工作并传递参数,可以使用如下代码:

// Create the Data object:
Data myData = new Data.Builder()
// We need to pass three integers: X, Y, and Z
.putInt(KEY_X_ARG, 42)
.putInt(KEY_Y_ARG, 421)
.putInt(KEY_Z_ARG, 8675309)
// … and build the actual Data object:
.build();

// …then create and enqueue a OneTimeWorkRequest that uses those arguments
OneTimeWorkRequest.Builder argsWorkBuilder =
new OneTimeWorkRequest.Builder(MathWorker.class)
.setInputData(myData);
OneTimeWorkRequest mathWork = argsWorkBuilder.build();
WorkManager.getInstance().enqueue(mathWork);

返回值在任务的 WorkStatus中可得到:

WorkManager.getInstance().getStatusById(mathWork.getId())
.observe(lifecycleOwner, status -> {

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

学习分享,共勉

Android高级架构师进阶之路

题外话,我在阿里工作多年,深知技术改革和创新的方向,Android开发以其美观、快速、高效、开放等优势迅速俘获人心,但很多Android兴趣爱好者所需的进阶学习资料确实不太系统,完整。今天我把我搜集和整理的这份学习资料分享给有需要的人

  • Android进阶知识体系学习脑图

  • Android进阶高级工程师学习全套手册

  • 对标Android阿里P7,年薪50w+学习视频

  • 大厂内部Android高频面试题,以及面试经历

77011619)]

  • Android进阶高级工程师学习全套手册

[外链图片转存中…(img-yvwE7pJW-1712077011619)]

  • 对标Android阿里P7,年薪50w+学习视频

[外链图片转存中…(img-rqzMugOQ-1712077011620)]

  • 大厂内部Android高频面试题,以及面试经历

[外链图片转存中…(img-cdKjeJ1G-1712077011620)]

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

  • 10
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值