Skip to content

Commit eb24f82

Browse files
committed
add WorkManager.md
1 parent c5fff67 commit eb24f82

File tree

2 files changed

+170
-0
lines changed

2 files changed

+170
-0
lines changed
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
Android WorkManager
2+
===
3+
4+
谷歌在今年的`Google I/O`上宣布了一项非常令人兴奋的功能,该功能允许开发人员执行传统上需要详细了解各种API级别和可用于这些API的后台任务库的后台任务(简单点说就是”管理一些要在后台工作的任务, – 即使你的应用没启动也能保证任务能被执行”),这就是[WorkManager](https://developer.android.com/reference/androidx/work/WorkManager),`WorkManager`提供了从其他`API`(例如`JobScheduler``Firebase.JobDispatcher``AlarmManager``Services`)中获得的功能,而无需研究哪种`API`可用于您的设备或`API`
5+
6+
这句话是什么意思?既然能用`JobScheduler``AlarmManager`等,何必再出来个`WorkManager`呢?其实`WorkManager`在底层也是看你是什么版本来选到底是`JobScheduler`,`AlamarManager`来做。
7+
`JobScheduler`是在`SDK`21中才有的,而且在`SDK`21中还有`Bug`,稳定可用是从`SDK`23开始的. 而`AlarmManager`一直存在,但是`AlarmManager`也不是最好的选择,
8+
注意:如果您的应用程序的目标是`API`级别26或更高,则当应用程序本身不在前台时,系统会对运行后台服务施加限制。在大多数情况下,您的应用程序应该使用预定作业。所以`WorkManager`在底层, 会根据你的设备情况, 选用`JobScheduler`,`Firebase``JobDispatcher`,或是`AlarmManager`
9+
10+
11+
`WorkManager`,它在应用被杀, 甚至设备重启后仍能保证你安排给他的任务能得到执行。那这样我们以后是不是可以把后台任务都用它来实现了?其实`Google`自己也说了:`WorkManager`并不是为了那种在应用内的后台线程而设计出来的. 这种需求你应该使用`ThreadPool`
12+
13+
具体的规则如下:
14+
15+
`WorkManager`根据以下标准在可用时使用对应的底层工作服务:
16+
17+
-`API 23+`使用`JobScheduler`
18+
-`API 14-22`
19+
- 如果在应用中使用了`Firebase JobDispatcher`并且有可选的`Firebase`依赖项就使用`Firebase JobDispatcher`
20+
- 否则使用自定义的`AlarmManager + BroadcastReceiver`的实现方式
21+
22+
23+
组成部分:
24+
25+
- `WorkManager`:通过对应的参数来接受`work`并排队执行`work`
26+
- `Worker`:通过实现`doWork()`方法来指定在后台执行的具体功能。
27+
- `WorkRequest`:代表一个独立的任务。它会告诉你哪个`worker`加入了,以及它需要满足哪些约束才能运行。`WorkRequest`是一个抽象类,您将使用[OneTimeWorkRequest](https://developer.android.com/reference/androidx/work/OneTimeWorkRequest)[PeriodicWorkRequest](https://developer.android.com/reference/androidx/work/PeriodicWorkRequest)
28+
- `WorkStatus`:为每个WorkRequest对象提供数据。
29+
30+
31+
32+
好了下面开始演示:
33+
34+
首先加入依赖:
35+
36+
```
37+
dependencies {
38+
def work_version = "1.0.0-alpha02"
39+
implementation "android.arch.work:work-runtime:$work_version"
40+
}
41+
```
42+
43+
- 继承`Worker`类并实现`doWork()`方法
44+
45+
```kotlin
46+
class MineWorker : Worker() {
47+
override fun doWork(): WorkerResult {
48+
Log.e("@@@", "dang dang dang !!!")
49+
return WorkerResult.SUCCESS
50+
}
51+
}
52+
```
53+
54+
- 接下来如果想要该`Worker`执行,需要调用`WorkManager`将该`Worker`添加到队列中
55+
56+
```kotlin
57+
class MainActivity : AppCompatActivity() {
58+
59+
override fun onCreate(savedInstanceState: Bundle?) {
60+
super.onCreate(savedInstanceState)
61+
setContentView(R.layout.activity_main)
62+
63+
val workRequest = OneTimeWorkRequest.Builder(MineWorker::class.java).build()
64+
val instance = WorkManager.getInstance()
65+
instance.enqueue(workRequest)
66+
67+
}
68+
}
69+
```
70+
71+
好了,执行下:
72+
```
73+
05-29 12:15:51.066 6360-6406/com.charon.workmanagerdemo E/@@@: dang dang dang !!!
74+
```
75+
76+
并没什么卵用,因为这个示例代码就上来就执行一次。 很显然这个不合理啊,我想给该`worker`添加一些限制条件,例如我想在手机充电时,并且有网的情况下执行某个任务,
77+
而且我想让它执行多次,这里可以通过`Constraints`来限制:
78+
79+
```kotlin
80+
override fun onCreate(savedInstanceState: Bundle?) {
81+
super.onCreate(savedInstanceState)
82+
setContentView(R.layout.activity_main)
83+
84+
val constraints = Constraints.Builder()
85+
.setRequiredNetworkType(NetworkType.CONNECTED)
86+
.setRequiresCharging(true)
87+
.build()
88+
89+
val workRequest = OneTimeWorkRequest.Builder(MineWorker::class.java)
90+
.setConstraints(constraints).build()
91+
92+
val instance = WorkManager.getInstance()
93+
instance.enqueue(workRequest)
94+
}
95+
```
96+
我们把手机网络关掉运行下,这次运行后并没有`log`打印。那现在把网络打开:
97+
98+
```
99+
05-29 12:21:02.061 7092-7241/? E/@@@: dang dang dang !!!
100+
```
101+
102+
103+
当然我们可以获取每个请求的状态,以及取消该请求:
104+
```kotlin
105+
val statusById: LiveData<WorkStatus> = instance.getStatusById(workRequest.id)
106+
instance.cancelWorkById(workRequest.id)
107+
```
108+
如果想要顺序的去执行不同的`OneTimeWorker`也是很方便的:
109+
```kotlin
110+
WorkContinuation chain1 = WorkManager.getInstance()
111+
.beginWith(workA)
112+
.then(workB);
113+
WorkContinuation chain2 = WorkManager.getInstance()
114+
.beginWith(workC)
115+
.then(workD);
116+
WorkContinuation chain3 = WorkContinuation
117+
.combine(chain1, chain2)
118+
.then(workE);
119+
chain3.enqueue();
120+
```
121+
122+
上面都是用了`OneTimeWorkRequest`,如果你想定期的去执行某一个`worker`的话,可以使用`PeriodicWorkRequest`:
123+
```kotlin
124+
val workRequest = PeriodicWorkRequest.Builder(MineWorker::class.java, 3, TimeUnit.SECONDS)
125+
.setConstraints(constraints)
126+
.setInputData(data)
127+
.build()
128+
```
129+
130+
但是我使用这个定期任务执行的时候也只是执行了一次,并没有像上面的代码中那样3秒执行一次,什么鬼?
131+
我们看看`PeriodicWorkRequest`的源码:
132+
133+
```kotlin
134+
/**
135+
* A class that represents a request for repeating work.
136+
*/
137+
138+
public final class PeriodicWorkRequest extends WorkRequest {
139+
140+
/**
141+
* The minimum interval duration for {@link PeriodicWorkRequest}, in milliseconds.
142+
* Based on {@see https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/job/JobInfo.java#110}.
143+
*/
144+
public static final long MIN_PERIODIC_INTERVAL_MILLIS = 15 * 60 * 1000L; // 15 minutes.
145+
```
146+
147+
上面说的很明白,最小间隔15分钟,- -
148+
149+
150+
总体来说,`WorkManager`并不是要取代线程池`AsyncTask/RxJava`.反而是像`AlarmManager`来做定时任务的意思.即保证你给它的任务能完成, 即使你的应用都没有被打开, 或是设备重启后也能让你的任务被执行.`WorkManager`在设计上设计得比较好.没有把`worker`,任务混为一谈,而是把它们解耦成`Worker`,`WorkRequest`.这样分层就清晰多了, 也好扩展.
151+
152+
153+
到了这里突然有了一个大胆的想法。看到没有它能保证任务的执行。
154+
我们之前写过一篇文章[Android卸载反馈](https://github.com/CharonChui/AndroidNote/blob/master/AdavancedPart/Android%E5%8D%B8%E8%BD%BD%E5%8F%8D%E9%A6%88.md)
155+
里面用到了`c`中的`fork`来保证存活,达到常驻内存的功能,如果`PeriodicWorkRequest`的最小间隔时间比较短不是15分钟的话,那这里是不是也可以用`WorkManager`来实现? 好了,不说了。
156+
157+
158+
159+
参考:
160+
161+
- [官方文档](https://developer.android.com/topic/libraries/architecture/workmanager)
162+
- [Codelabs android-workmanager](https://codelabs.developers.google.com/codelabs/android-workmanager/#0)
163+
- [示例代码](https://github.com/googlecodelabs/android-workmanager)
164+
165+
---
166+
167+
- 邮箱 :charon.chui@gmail.com
168+
- Good Luck!

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ Android学习笔记
128128
- [MaterialDesign使用][83]
129129
- [RecyclerView专题][84]
130130
- [ConstraintLaayout简介][194]
131+
- [Android WorkManager][208]
131132

132133
- [Java基础及算法][53]
133134
- [八种排序算法][189]
@@ -444,6 +445,7 @@ Android学习笔记
444445
[205]: https://github.com/CharonChui/AndroidNote/blob/master/Dagger2/6.Dagger2Android%E7%A4%BA%E4%BE%8B%E4%BB%A3%E7%A0%81(%E5%85%AD).md "6.Dagger2Android示例代码(六).md"
445446
[206]: https://github.com/CharonChui/AndroidNote/blob/master/Dagger2/7.Dagger2%E4%B9%8Bdagger-android(%E4%B8%83).md "7.Dagger2之dagger-android(七).md"
446447
[207]: https://github.com/CharonChui/AndroidNote/blob/master/Dagger2/8.Dagger2%E4%B8%8EMVP(%E5%85%AB).md "8.Dagger2与MVP(八).md"
448+
[208]: https://github.com/CharonChui/AndroidNote/blob/master/Dagger2/8.Dagger2%E4%B8%8EMVP(%E5%85%AB).md "Android WorkManager.md"
447449

448450

449451

0 commit comments

Comments
 (0)