Android Jetpack - 使用WorkManager处理简单的后台任务

简介: **阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:[https://space.bilibili.com/474380680](https://links.jianshu.com/go?to=https%3A%2F%2Fspace.

阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680

当我们讨论后台处理任务的时候,一般可能涉及的行为类型有下面一些类型,例如:

  • 发送程序运行日志
  • 上传图片和视频
  • 同步数据
  • 处理数据

这些行为都需要在后台进行操作,在Android平台上,我们可以利用如下的这些可选方式来实现后台任务:

google_io_2018_android_jetpack_workmanager_01

那么到底我们如何做出合理的选择呢?过去的几年,Android系统随着版本的更新针对电量优化这一块做出了不同程度的限制优化,例如在Android M上的Doze Mode,Android N上的Limit Implicit Broadcast,Android O上的Background Service Limitations以及最新的Android P上面的App Standby Buckets。为了确保后台任务对电量的消耗影响足够小,对待后台任务的处理要更加的慎重小心。

0)Types of Background Work

通常来说,我们可以把所有的后台任务按照任务紧迫性(是马上需要执行的任务/还是可以缓期执行的任务)和任务重要性(是确保一定要被执行的任务/还是最好能够执行的任务)进行四象限的划分。通常来说对于非确保一定要执行的任务,无论时间是否紧迫,我们都可以使用ThreadPool来完成这个任务。对于那些比较重要的又时间紧迫的任务,我们一般会使用Foreground Service来完成这个操作。比较有有意思的是最后一个象限:那些希望确保可以被执行但是又可以接受延期执行的任务。这些任务可以使用JobScheduler/JobDispatcher/AlarmManager/BroadcastReceivers来完成。WorkManager也刚好是用来解决这一类的问题的。

google_io_2018_android_jetpack_workmanager_02

1)WorkManager Features

下面是WorkManager的一些突出特点:

  • 确保可以被执行,并且可以设置执行的限定条件(例如仅仅在有网络连接的时候才进行图片的上传)
  • 同样受到系统后台任务的限制管理(如APP进入Doze Mode的时候,任务不会被执行)
  • 向后兼容;无论是否集成了Google Play Service服务,都是向后兼容的
  • 任务可查询;如论当下在执行什么任务,都是可以直接查询获取到任务状态信息的(例如正在运行的状态是什么,结果是成功还是失败了)
  • 任务可串联;例如执行任务A之前需要任务B或者C先进行完成
  • 任务伺机执行:在条件满足的时候会尽快尝试触发任务的执行,不需要等待JobScheduler的唤醒,也不会需要等待JobScheduler进行批量任务处理的才被执行

WorkManager中的核心类有:

  • Worker:这个类是真正干活的,工作逻辑都在这里面
  • WorkRequest:
    • OneTimeWorkRequest:只执行一次的任务请求
    • PeriodicWorkRequest:重复执行的任务请求

举个例子:图片上传的后台任务是如何执行的。下面是上传图片的Worker示例:

google_io_2018_android_jetpack_workmanager_03

google_io_2018_android_jetpack_workmanager_04

其中uploadPhoto是执行在后台线程的,返回值可以是成功或者失败,还可以是重试,这意味着告诉系统这个任务需要后面找机会重新执行。有了上面那些基础,接下去就只需要利用Worker创建对应的WorkRequest,并并添加到WorkManager的执行队列中就好了。

google_io_2018_android_jetpack_workmanager_05

正常情况下,放到任务队列中的任务会被立马执行,可是如果遇到网络连接失败的情况,这样就会执行失败。此时我们就可以通过添加限定执行条件来达到优化的目的,例如设置限定只在网络连接成功的时候才进行任务的执行。

google_io_2018_android_jetpack_workmanager_06

2)Observing Work

有了上面的任务触发逻辑之后,那么如何做任务的监听呢?例如正在处理过程中显示一个进度圈,处理成功的时候消失进度等等。我们可以使用如下演示的范例来监听任务的执行状态。

google_io_2018_android_jetpack_workmanager_07

LiveData是Google开发的一个感知生命周期的架构组件。使用这个组件来hook监听request任务的WorkStatus。在WorkStatus里面有任务的id和status,其中status有6种状态,分别是ENQUEUED,RUNNING,SUCCEEDED,FAILED,BLOCKED,CANCELLED

3)Chaining Work

通常来说,上传任务真正被执行之前,我们会对数据做一次压缩,因为每一个任务都需要在后台进行,并且需要保证执行顺序。我们可以使用下面的示例方式,先进行压缩,成功之后,再进行上传。

google_io_2018_android_jetpack_workmanager_08

只所以可以类似上面那样写,是因为每一步任务返回的都是WorkContinuation,使用它可以对不同的任务进行串联。

google_io_2018_android_jetpack_workmanager_09

如果想要多项任务并发执行,可以同时建立多个WorkRequest,一起交给WorkManager进行执行(根据CPU核心数和架构的不同,并发数量有所差异)。

google_io_2018_android_jetpack_workmanager_10

我们再把任务链设置的更加复杂一点,例如图片要先分别经过不同的滤镜处理,之后再进行压缩,最后才可以上传,那么使用WorkManager该如何实行呢?

google_io_2018_android_jetpack_workmanager_11

4)Inputs and Outputs

任务之间如何进行数据的传递呢?在介绍这个之前,我们需要了解下什么叫做MapReduce。例如,我们想要从三本书里面找出使用最多的词语,先把所有词语都进行计算一遍,然后对词语的使用次数进行排序,最后才可以找出使用最多的词语,我们把这个行为叫做MapReduce。

使用WorkManager的输入和输出数据具备如下的特点:

  • 简单的KEY-VALUE
    • KEY都是String类型的
    • VALUE可以是基础数据类型和String
  • 数据本身已经做了序列化处理
  • 限定10KB大小以内

我们使用如下的方式进行输入的数据传递,构造一个map类型的Data,通过WorkManager的setInputData()给Worker进行传输数据。

google_io_2018_android_jetpack_workmanager_12

接下去Worker可以通过getInputData()来获取到输入的数据。

google_io_2018_android_jetpack_workmanager_13

一般来说,我们会需要把处理的结果进行返回,那么使用setOutputData()来完成这个操作就可以了

google_io_2018_android_jetpack_workmanager_14

有意思的事情是,在任务链中,输出的数据一般就是下一个任务的输入。那么当某个环节的一个任务是由多个任务的输出构成的时候,改如何处理呢?

google_io_2018_android_jetpack_workmanager_15

为了解决这个问题,我们需要了解InputMergers,顾名思义,它是用来合并多个输入数据变成一个的。一般来说有两种合并实现的方式(也可以自己自定义)

  • OverwritingInputMerger(系统默认):按照输入数据的先后顺序,相同KEY会被覆盖,不同的KEY内容会被保留

google_io_2018_android_jetpack_workmanager_16

  • ArrayCreatingInputMerger:相同KEY的VALUE值进行合并,需要确保VALUE是相同数据类型的,否者会出现异常

google_io_2018_android_jetpack_workmanager_17

5)Cancelling Work

想要取消一个任务,只需要调用cancelWorkById()就好了,但是需要注意的是,这个方法只是尽力而为,因为相关想要取消的任务有可能已经在运行,也有可能已经执行结束了。

google_io_2018_android_jetpack_workmanager_18

6)Tags

前面我们有提到过好几次任务id,这个id是系统自动生成的,类似UUID这样的数值。我们无法通过这个id来判断这是一个什么样的任务,tags就是为了解决这个任务可读性的问题的。我们可以给任务打上一个或者多个tag来标记这是一个什么样的任务,然后可以通过这个tag来查询,取消任务等等。

google_io_2018_android_jetpack_workmanager_19

google_io_2018_android_jetpack_workmanager_20

使用Tag可以给我们提供很大的帮助,我们可以根据不同的模块和依赖给任务设置不同的tag,也可以根据任务的类型进行设置tag,这样就可以方便的进行批量任务操作了。

7)Unique Work

为了解决多个任务的同步问题,引入了Unique Work的机制。它有三种类型,分别为

  • KEEP:新启动的Unique任务,如果之前已经存在,就继续保留旧的任务,如果不存在,则触发这次新的任务

google_io_2018_android_jetpack_workmanager_21

  • REPLACE:取消或者删除之前的所有此类Unique任务,使用这次的任务作为最新任务,重复调用多次的时候,会以最后一次为准

google_io_2018_android_jetpack_workmanager_22

  • APPEND:按照添加顺序,逐个执行任务

google_io_2018_android_jetpack_workmanager_23

8)Periodic Work

重复任务和我们之前认知的其他重复任务一样,具备一些如下的特点:

  • 最短间隔时间15分钟(和JobScheduler一样)
  • 同样受系统doze mode和其他的后台任务限制
  • 不可以有任务链
  • 不可以有触发延迟

9)Under The Hood

当系统接受到一个Work任务的时候,会先记录到自己的任务数据库中,接下去系统是如何判断执行的呢?如果任务符合当下执行的条件,那么会由Executor(可自定义,系统默认有实现)立即执行;如果我们的进程已经被杀死,那么任务什么时候可以被执行呢?如果设备运行在>=API 23,会交给JobScheduler触发IPC请求,唤醒我们的进程进行任务的执行;如果设备运行在< API 23的情况下,系统会判断设备是否有Firebase JobDispatcher,如果有会交给它进行处理;如果那些Google Play Service服务都没有,系统会使用AlarmManager和BroadcastReceivers的方式在合适的时候唤醒应用进行处理。

google_io_2018_android_jetpack_workmanager_24

10)Best Practice

  • 何时使用WorkManager呢?下面给一些最佳实践的例子:
    • OK:上传图片和视频
    • OK:解析数据并存储到数据库中
    • NO:从调色板中获取颜色并设置到图片上
    • NO:解析数据并呈现到视图上进行显示
    • NO:处理交易的请求
  • 不要使用WorkManager来存储数据,记得只有10kb的限制
  • 记得给不同的任务设置各自的执行限定条件,避免无谓的资源浪费

google_io_2018_android_jetpack_workmanager_25
原文作者:胡凯
原文链接http://hukai.me/google-io-2018-android-jetpack-workmanager/
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680

相关文章
|
7月前
|
存储 缓存 Android开发
安卓Jetpack Compose+Kotlin, 使用ExoPlayer播放多个【远程url】音频,搭配Okhttp库进行下载和缓存,播放完随机播放下一首
这是一个Kotlin项目,使用Jetpack Compose和ExoPlayer框架开发Android应用,功能是播放远程URL音频列表。应用会检查本地缓存,如果文件存在且大小与远程文件一致则使用缓存,否则下载文件并播放。播放完成后或遇到异常,会随机播放下一首音频,并在播放前随机设置播放速度(0.9到1.2倍速)。代码包括ViewModel,负责音频管理和播放逻辑,以及UI层,包含播放和停止按钮。
|
7月前
|
安全 Java Android开发
安卓开发中的新趋势:Kotlin与Jetpack的完美结合
【6月更文挑战第20天】在不断进化的移动应用开发领域,Android平台以其开放性和灵活性赢得了全球开发者的青睐。然而,随着技术的迭代,传统Java语言在Android开发中逐渐显露出局限性。Kotlin,一种现代的静态类型编程语言,以其简洁、安全和高效的特性成为了Android开发中的新宠。同时,Jetpack作为一套支持库、工具和指南,旨在帮助开发者更快地打造优秀的Android应用。本文将探讨Kotlin与Jetpack如何共同推动Android开发进入一个新的时代,以及这对开发者意味着什么。
|
7月前
|
存储 数据库 Android开发
安卓Jetpack Compose+Kotlin,支持从本地添加音频文件到播放列表,支持删除,使用ExoPlayer播放音乐
为了在UI界面添加用于添加和删除本地音乐文件的按钮,以及相关的播放功能,你需要实现以下几个步骤: 1. **集成用户选择本地音乐**:允许用户从设备中选择音乐文件。 2. **创建UI按钮**:在界面中创建添加和删除按钮。 3. **数据库功能**:使用Room数据库来存储音频文件信息。 4. **更新ViewModel**:处理添加、删除和播放音频文件的逻辑。 5. **UI实现**:在UI层支持添加、删除音乐以及播放功能。
|
7月前
|
数据管理 API 数据库
探索Android Jetpack:现代安卓开发的利器
Android Jetpack是谷歌为简化和优化安卓应用开发而推出的一套高级组件库。本文深入探讨了Jetpack的主要构成及其在应用开发中的实际运用,展示了如何通过使用这些工具来提升开发效率和应用性能。
|
3月前
|
测试技术 数据库 Android开发
深入解析Android架构组件——Jetpack的使用与实践
本文旨在探讨谷歌推出的Android架构组件——Jetpack,在现代Android开发中的应用。Jetpack作为一系列库和工具的集合,旨在帮助开发者更轻松地编写出健壮、可维护且性能优异的应用。通过详细解析各个组件如Lifecycle、ViewModel、LiveData等,我们将了解其原理和使用场景,并结合实例展示如何在实际项目中应用这些组件,提升开发效率和应用质量。
66 6
|
4月前
|
编译器 Android开发 开发者
带你了解Android Jetpack库中的依赖注入框架:Hilt
本文介绍了Hilt,这是Google为Android开发的依赖注入框架,基于Dagger构建,旨在简化依赖注入过程。Hilt通过自动化的组件和注解减少了DI的样板代码,提高了应用的可测试性和可维护性。文章详细讲解了Hilt的主要概念、基本用法及原理,帮助开发者更好地理解和应用Hilt。
115 8
|
4月前
|
安全 Java Android开发
探索安卓应用开发的新趋势:Kotlin和Jetpack Compose
在安卓应用开发领域,随着技术的不断进步,新的编程语言和框架层出不穷。Kotlin作为一种现代的编程语言,因其简洁性和高效性正逐渐取代Java成为安卓开发的首选语言。同时,Jetpack Compose作为一个新的UI工具包,提供了一种声明式的UI设计方法,使得界面编写更加直观和灵活。本文将深入探讨Kotlin和Jetpack Compose的特点、优势以及如何结合使用它们来构建现代化的安卓应用。
115 4
|
6月前
|
存储 数据库 Android开发
🔥Android Jetpack全解析!拥抱Google官方库,让你的开发之旅更加顺畅无阻!🚀
【7月更文挑战第28天】在Android开发中追求高效稳定的路径?Android Jetpack作为Google官方库集合,是你的理想选择。它包含多个独立又协同工作的库,覆盖UI到安全性等多个领域,旨在减少样板代码,提高开发效率与应用质量。Jetpack核心组件如LiveData、ViewModel、Room等简化了数据绑定、状态保存及数据库操作。引入Jetpack只需在`build.gradle`中添加依赖。例如,使用Room进行数据库操作变得异常简单,从定义实体到实现CRUD操作,一切尽在掌握之中。拥抱Jetpack,提升开发效率,构建高质量应用!
125 4
|
6月前
|
存储 移动开发 Android开发
使用kotlin Jetpack Compose框架开发安卓app, webview中h5如何访问手机存储上传文件
在Kotlin和Jetpack Compose中,集成WebView以支持HTML5页面访问手机存储及上传音频文件涉及关键步骤:1) 添加`READ_EXTERNAL_STORAGE`和`WRITE_EXTERNAL_STORAGE`权限,考虑Android 11的分区存储;2) 配置WebView允许JavaScript和文件访问,启用`javaScriptEnabled`、`allowFileAccess`等设置;3) HTML5页面使用`<input type="file">`让用户选择文件,利用File API;
|
7月前
|
JavaScript Java Android开发
kotlin安卓在Jetpack Compose 框架下跨组件通讯EventBus
**EventBus** 是一个Android事件总线库,简化组件间通信。要使用它,首先在Gradle中添加依赖`implementation &#39;org.greenrobot:eventbus:3.3.1&#39;`。然后,可选地定义事件类如`MessageEvent`。在活动或Fragment的`onCreate`中注册订阅者,在`onDestroy`中反注册。通过`@Subscribe`注解方法处理事件,如`onMessageEvent`。发送事件使用`EventBus.getDefault().post()`。

热门文章

最新文章