张文永 發表於 2020-7-10 13:44:00

Android开发 WorkManager详解

<h1><span style="color: rgba(0, 128, 128, 1)">版权声明</span></h1>
<p>本文来自博客园,作者:观心静&nbsp;,转载请注明原文链接:https://www.cnblogs.com/guanxinjing/p/13278814.html</p>
<div>本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。</div>
<h1><span style="color: rgba(0, 128, 128, 1)">前言</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">  用于支持Android在后台的任务运行,提供延迟、周期性,约束性需求的后台任务。<span style="color: rgba(0, 0, 0, 1)">任务是交给系统统一调度的</span>,适合一些轻量级的后台功能使用。还能支持在Doze模式下运行后台任务,WorkManager会在Doze模式的窗口期运行任务。</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">  <span style="color: rgba(0, 0, 0, 1)">WorkManager</span>的设计用意就是取代后台服务,由系统统一管理你的周期性后台服务,并且自动兼容API23以下,API23以下自动在底层使用AlarmManager + BroadcastReceiver实现,而高于API23会使用JobScheduler实现。所以这是一个能取代闹钟定时器的后台功能。并且在高版本里闹钟功能其实已经不太能正常使用了。使用<span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">WorkManager取代所有周期或者长时间的后台工作是必需必要的。</span></span></span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">  转载请注明来源:https://www.cnblogs.com/guanxinjing/p/13278814.html</span></span></span></p>
<h1><span style="color: rgba(0, 128, 128, 1)">WorkManager特性</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">  1.可以在设备睡眠时执行任务,但是只在唤醒窗口期间执行doWork,所以长时间的定位触发并不是准确的(请了解Doze模式)</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">  2.周期任务只能最小15分钟触发一次</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">  3.<strong><span style="color: rgba(255, 0, 0, 1)">请注意这个特性!&nbsp;</span></strong>在任务创建并且入队后,app被后台清理了,任务不会执行. 但是在app重新启动后,只要定时时间已经到达,任务就会在app启动的时候立刻执行. 这个特性引起的问题请阅读这个博客&nbsp;https://www.cnblogs.com/guanxinjing/p/15951431.html</span></p>
<p>&nbsp;</p>
<h1><span style="color: rgba(0, 128, 128, 1)">依赖</span></h1>
<div class="cnblogs_code">
<pre>      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> (Java only)</span>
      implementation "androidx.work:work-runtime:2.3.4"<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">java 语言选这个

      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Kotlin + coroutines</span>
      implementation "androidx.work:work-runtime-ktx:2.3.4"<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">kotlin 选这个

      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> optional - RxJava2 support</span>
      implementation "androidx.work:work-rxjava2:2.3.4"<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">配合rxjava2 使用</span></pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">&nbsp;一个简单的小Demo快速了解</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">照例用一个极简的demo来运行体验一下。</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">创建work,继承<span style="color: rgba(0, 0, 0, 1)">Worker</span>,实现doWork方法,这个方法是执行后台功能实现的地方。</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> MyWork <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> Worker {

    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> MyWork(@NonNull Context context, @NonNull WorkerParameters workerParams) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">(context, workerParams);
    }

    @NonNull
    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Result doWork() {
      Log.e(</span>"调试_临时_log", "this_doWork"<span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Result.success();<span style="color: rgba(0, 128, 0, 1)">//<span style="color: rgba(0, 128, 0, 1)">结果返回为成功</span></span>
    }
}</span></pre>
</div>
<p>创建Work请求并且添加到<span style="color: rgba(0, 0, 0, 1)">WorkManager里:</span></p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> startWork(){
      OneTimeWorkRequest oneTimeWorkRequest </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> OneTimeWorkRequest.Builder(MyWork.<span style="color: rgba(0, 0, 255, 1)">class</span>)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">一次性Work请求</span>
                .setInitialDelay(10, TimeUnit.SECONDS)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">初始延迟10秒</span>
<span style="color: rgba(0, 0, 0, 1)">                .build();
      WorkManager.getInstance(</span><span style="color: rgba(0, 0, 255, 1)">this</span>).enqueue(oneTimeWorkRequest);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">添加到WorkManager队列中</span>
    }</pre>
</div>
<p>这样我们就可以在10秒后看到log了。</p>
<h1><span style="color: rgba(0, 128, 128, 1)">Worker数据的传入与获取</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">在work里</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> MyWork <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> Worker {

    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> MyWork(@NonNull Context context, @NonNull WorkerParameters workerParams) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">(context, workerParams);
    }
   
    @NonNull
    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Result doWork() {
      String data </span>= getInputData().getString("putData"<span style="color: rgba(0, 0, 0, 1)">);
      Log.e(</span>"调试_临时_log", "传入数据 putData = " +<span style="color: rgba(0, 0, 0, 1)"> data);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Result.success();
    }
}</span></pre>
</div>
<p>在Activity里创建work请求,并且传入数据</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> startWork(){
      Data data </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Data.Builder().putString("putData","输入数据").build();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">创建需要传入的数据,注意不支持序列化数据传入</span>
      OneTimeWorkRequest oneTimeWorkRequest = <span style="color: rgba(0, 0, 255, 1)">new</span> OneTimeWorkRequest.Builder(MyWork.<span style="color: rgba(0, 0, 255, 1)">class</span>)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">一次性Work请求</span>
                .setInitialDelay(2<span style="color: rgba(0, 0, 0, 1)">, TimeUnit.SECONDS)
                .setInputData(data)
                .build();
      WorkManager.getInstance(</span><span style="color: rgba(0, 0, 255, 1)">this</span>).enqueue(oneTimeWorkRequest);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">添加到WorkManager队列中</span>
    }</pre>
</div>
<p>结果:</p>
<div class="cnblogs_code">
<pre>2020-07-10 17:51:10.638 24649-24698/com.yt.demo E/调试_临时_log: 传入数据 putData = 输入数据</pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">work的返回结果与监听状态</span></h1>
<p>处理了后台任务后总会有成功与否的结果。</p>
<h4>在doWork方法里返回结果:</h4>
<p>一共有3种结果可以返回,如下注释:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">    @NonNull
    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Result doWork() {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Result.success();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">      Result.success();</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">成功
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">      Result.failure();</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">失败
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">      Result.retry();</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">重试</span>
    }</pre>
</div>
<p>另外成功与失败的结果还能携带数据返回。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">    @NonNull
    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Result doWork() {
      Data data </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Data.Builder().putString("data", "返回数据"<span style="color: rgba(0, 0, 0, 1)">).build();
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Result.success(data);
    }</span></pre>
</div>
<h4>Activity里监听work的状态:</h4>
<p><strong>请注意!</strong>在这里的监听的返回的数据是LiveData。 这意味着只有当前Activity或者Fragment在前台时才能接收到此数据。</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> startWork(){
      OneTimeWorkRequest oneTimeWorkRequest </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> OneTimeWorkRequest.Builder(MyWork.<span style="color: rgba(0, 0, 255, 1)">class</span>)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">一次性Work请求</span>
                .setInitialDelay(5<span style="color: rgba(0, 0, 0, 1)">, TimeUnit.SECONDS)
                .build();
      WorkManager.getInstance(</span><span style="color: rgba(0, 0, 255, 1)">this</span>).getWorkInfoByIdLiveData(oneTimeWorkRequest.getId()).observe(<span style="color: rgba(0, 0, 255, 1)">this</span>, <span style="color: rgba(0, 0, 255, 1)">new</span> Observer&lt;WorkInfo&gt;<span style="color: rgba(0, 0, 0, 1)">() {
            @Override
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onChanged(WorkInfo workInfo) {
                </span><span style="color: rgba(0, 0, 255, 1)">switch</span><span style="color: rgba(0, 0, 0, 1)"> (workInfo.getState()){
                  </span><span style="color: rgba(0, 0, 255, 1)">case</span><span style="color: rgba(0, 0, 0, 1)"> BLOCKED:
                        Log.e(</span>"调试_临时_log", "堵塞"<span style="color: rgba(0, 0, 0, 1)">);
                        </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
                  </span><span style="color: rgba(0, 0, 255, 1)">case</span><span style="color: rgba(0, 0, 0, 1)"> RUNNING:
                        Log.e(</span>"调试_临时_log", "正在运行"<span style="color: rgba(0, 0, 0, 1)">);
                        </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
                  </span><span style="color: rgba(0, 0, 255, 1)">case</span><span style="color: rgba(0, 0, 0, 1)"> ENQUEUED:
                        Log.e(</span>"调试_临时_log", "任务入队"<span style="color: rgba(0, 0, 0, 1)">);
                        </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
                  </span><span style="color: rgba(0, 0, 255, 1)">case</span><span style="color: rgba(0, 0, 0, 1)"> CANCELLED:
                        Log.e(</span>"调试_临时_log", "取消"<span style="color: rgba(0, 0, 0, 1)">);
                        </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
                  </span><span style="color: rgba(0, 0, 255, 1)">case</span><span style="color: rgba(0, 0, 0, 1)"> FAILED:
                        Log.e(</span>"调试_临时_log", "失败"<span style="color: rgba(0, 0, 0, 1)">);
                        </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
                  </span><span style="color: rgba(0, 0, 255, 1)">case</span><span style="color: rgba(0, 0, 0, 1)"> SUCCEEDED:
                        Log.e(</span>"调试_临时_log", "成功"<span style="color: rgba(0, 0, 0, 1)">);
                        Log.e(</span>"调试_临时_log", "this_data = " + workInfo.getOutputData().getString("data"<span style="color: rgba(0, 0, 0, 1)">));
                        </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
                }

            }
      });
      WorkManager.getInstance(</span><span style="color: rgba(0, 0, 255, 1)">this</span>).enqueue(oneTimeWorkRequest);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">添加到WorkManager队列中</span>
    }</pre>
</div>
<p>结果:</p>
<div class="cnblogs_code">
<pre>      2020-07-10 20:11:20.088 31078-31078/com.yt.demo E/<span style="color: rgba(0, 0, 0, 1)">调试_临时_log: 任务入队
      </span>2020-07-10 20:11:25.172 31078-31078/com.yt.demo E/<span style="color: rgba(0, 0, 0, 1)">调试_临时_log: 正在运行
      </span>2020-07-10 20:11:25.195 31078-31078/com.yt.demo E/<span style="color: rgba(0, 0, 0, 1)">调试_临时_log: 成功
      </span>2020-07-10 20:11:25.195 31078-31078/com.yt.demo E/调试_临时_log: this_data = 返回数据</pre>
</div>
<h4>不选择监听,即刻获得某个Work的当前状态值</h4>
<div class="cnblogs_code">
<pre>               <span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
                  WorkInfo workInfo </span>= WorkManager.getInstance(MainActivity.<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">).getWorkInfoById(mOneTimeWorkRequest.getId()).get();
                  Log.e(</span>"调试_临时_log", "this_" +<span style="color: rgba(0, 0, 0, 1)"> workInfo.getState());
                } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (ExecutionException e) {
                  e.printStackTrace();
                } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (InterruptedException e) {
                  e.printStackTrace();
                }</span></pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">work的进度发布</span></h1>
<p>有时候有需求需要知道work任务执行的进度。下面的MyWork模拟发送耗时任务进度,使用<strong><span style="color: rgba(0, 0, 0, 1)">setProgressAsync</span></strong>方法发布进度。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> MyWork <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> Worker {

    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> MyWork(@NonNull Context context, @NonNull WorkerParameters workerParams) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">(context, workerParams);
    }

    @NonNull
    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Result doWork() {
      </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i &lt; 10; i++<span style="color: rgba(0, 0, 0, 1)">) {
            Data data </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Data.Builder().putInt("Progress"<span style="color: rgba(0, 0, 0, 1)">, i).build();
            setProgressAsync(data);
            </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
                Thread.sleep(</span>1000<span style="color: rgba(0, 0, 0, 1)">);
            } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (InterruptedException e) {
                e.printStackTrace();
            }
      }
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Result.success();
    }
}</span></pre>
</div>
<p>监听进度:</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> startWork() {
      OneTimeWorkRequest oneTimeWorkRequest </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> OneTimeWorkRequest.Builder(MyWork.<span style="color: rgba(0, 0, 255, 1)">class</span>)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">一次性Work请求</span>
                .setInitialDelay(5<span style="color: rgba(0, 0, 0, 1)">, TimeUnit.SECONDS)
                .build();
      WorkManager.getInstance(</span><span style="color: rgba(0, 0, 255, 1)">this</span>).getWorkInfoByIdLiveData(oneTimeWorkRequest.getId()).observe(<span style="color: rgba(0, 0, 255, 1)">this</span>, <span style="color: rgba(0, 0, 255, 1)">new</span> Observer&lt;WorkInfo&gt;<span style="color: rgba(0, 0, 0, 1)">() {
            @Override
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onChanged(WorkInfo workInfo) {
                </span><span style="color: rgba(0, 0, 255, 1)">if</span> (workInfo.getState() ==<span style="color: rgba(0, 0, 0, 1)"> WorkInfo.State.RUNNING) {
                  Log.e(</span>"调试_临时_log", "当前进度 = " + workInfo.getProgress().getInt("Progress", -1<span style="color: rgba(0, 0, 0, 1)">));
                }
            }
      });
      WorkManager.getInstance(</span><span style="color: rgba(0, 0, 255, 1)">this</span>).enqueue(oneTimeWorkRequest);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">添加到WorkManager队列中</span>
    }</pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">Work的停止</span></h1>
<p>work的停止,只会work在运行时执行<span style="color: rgba(0, 0, 0, 1)">onStopped</span>,已经执行完成去取消任务是不会触发onStopped方法的。</p>
<p>work里的代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> MyWork <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> Worker {
    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span> mIsStop = <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> MyWork(@NonNull Context context, @NonNull WorkerParameters workerParams) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">(context, workerParams);
    }

    @NonNull
    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Result doWork() {
      </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i &lt; 10; i++<span style="color: rgba(0, 0, 0, 1)">) {
            </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (mIsStop){
                </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
            }
            Data data </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Data.Builder().putInt("Progress"<span style="color: rgba(0, 0, 0, 1)">, i).build();
            setProgressAsync(data);
            </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
                Thread.sleep(</span>1000<span style="color: rgba(0, 0, 0, 1)">);
            } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (InterruptedException e) {
                e.printStackTrace();
            }
      }
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Result.success();
    }

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onStopped() {
      Log.e(</span>"调试_临时_log", "this_onStopped"<span style="color: rgba(0, 0, 0, 1)">);
      mIsStop </span>= <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onStopped();
    }
}</span></pre>
</div>
<p>Activity代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> MainActivity <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> AppCompatActivity {
    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> ActivityMianDemoBinding mBinding;
    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> OneTimeWorkRequest oneTimeWorkRequest;

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onCreate(Bundle savedInstanceState) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onCreate(savedInstanceState);
      mBinding </span>=<span style="color: rgba(0, 0, 0, 1)"> ActivityMianDemoBinding.inflate(getLayoutInflater());
      setContentView(mBinding.getRoot());
      mBinding.btn1.setOnClickListener(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> View.OnClickListener() {
            @Override
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onClick(View view) {
                oneTimeWorkRequest </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> OneTimeWorkRequest.Builder(MyWork.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">)
                        .setInitialDelay(</span>5<span style="color: rgba(0, 0, 0, 1)">, TimeUnit.SECONDS)
                        .build();
                WorkManager.getInstance(MainActivity.</span><span style="color: rgba(0, 0, 255, 1)">this</span>).getWorkInfoByIdLiveData(oneTimeWorkRequest.getId()).observe(MainActivity.<span style="color: rgba(0, 0, 255, 1)">this</span>, <span style="color: rgba(0, 0, 255, 1)">new</span> Observer&lt;WorkInfo&gt;<span style="color: rgba(0, 0, 0, 1)">() {
                  @Override
                  </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onChanged(WorkInfo workInfo) {
                        </span><span style="color: rgba(0, 0, 255, 1)">switch</span><span style="color: rgba(0, 0, 0, 1)"> (workInfo.getState()) {
                            </span><span style="color: rgba(0, 0, 255, 1)">case</span><span style="color: rgba(0, 0, 0, 1)"> RUNNING:
                              Log.e(</span>"调试_临时_log", "当前进度 = " + workInfo.getProgress().getInt("Progress", -1<span style="color: rgba(0, 0, 0, 1)">));
                              </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
                            </span><span style="color: rgba(0, 0, 255, 1)">case</span><span style="color: rgba(0, 0, 0, 1)"> CANCELLED:
                              Log.e(</span>"调试_临时_log", "this_取消任务"<span style="color: rgba(0, 0, 0, 1)">);
                              </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
                        }
                  }
                });
                WorkManager.getInstance(MainActivity.</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">).enqueue(oneTimeWorkRequest);

            }
      });
      mBinding.btn2.setOnClickListener(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> View.OnClickListener() {
            @Override
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onClick(View view) {
                WorkManager.getInstance(MainActivity.</span><span style="color: rgba(0, 0, 255, 1)">this</span>).cancelWorkById(oneTimeWorkRequest.getId());<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">取消任务</span>
<span style="color: rgba(0, 0, 0, 1)">            }
      });
    }
}</span></pre>
</div>
<p>结果:</p>
<div class="cnblogs_code">
<pre>2020-07-13 11:38:27.160 14030-14030/com.yt.cccomponentizationdemo E/调试_临时_log: 当前进度 = 0
2020-07-13 11:38:28.210 14030-14030/com.yt.cccomponentizationdemo E/调试_临时_log: 当前进度 = 1
2020-07-13 11:38:29.199 14030-14030/com.yt.cccomponentizationdemo E/调试_临时_log: 当前进度 = 2
2020-07-13 11:38:29.902 14030-14075/com.yt.cccomponentizationdemo E/<span style="color: rgba(0, 0, 0, 1)">调试_临时_log: this_onStopped
</span>2020-07-13 11:38:29.973 14030-14030/com.yt.cccomponentizationdemo E/调试_临时_log: this_取消任务</pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">了解创建Work请求</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">请求有两种</span></p>
<ul>
<li>OneTimeWorkRequest&nbsp;&nbsp;&nbsp;&nbsp; 一次性Work请求</li>
<li>PeriodicWorkRequest  周期性Work请求</li>
</ul>
<h2>OneTimeWorkRequest</h2>
<p><strong>&nbsp;设置初始延迟时间 <span style="color: rgba(0, 0, 0, 1)">setInitialDelay</span></strong></p>
<p>上面已经有很多例子了,就不在重复说明了</p>
<div class="cnblogs_code">
<pre>                OneTimeWorkRequest oneTimeWorkRequest = <span style="color: rgba(0, 0, 255, 1)">new</span> OneTimeWorkRequest.Builder(MyWork.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">)
                        .setInitialDelay(</span>2, TimeUnit.SECONDS)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置初始延时时间</span>
                        .build();</pre>
</div>
<p><strong>设置传入数据 <span style="color: rgba(0, 0, 0, 1)">setInputData</span></strong></p>
<p>上面已经有很多例子了,就不在重复说明了</p>
<div class="cnblogs_code">
<pre>                Data data = <span style="color: rgba(0, 0, 255, 1)">new</span> Data.Builder().putString("data","demo"<span style="color: rgba(0, 0, 0, 1)">).build();
                OneTimeWorkRequest oneTimeWorkRequest </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> OneTimeWorkRequest.Builder(MyWork.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">)
                        .setInputData(data)</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置传入数据</span>
                        .build();</pre>
</div>
<p><strong>添加Tag addTag</strong></p>
<p>添加tag可以,按组控制work. 比如多个OneTimeWorkRequest 都添加相同的tag, 再用这个tag进行统一的取消.</p>
<div class="cnblogs_code">
<pre>       OneTimeWorkRequest oneRequest = <span style="color: rgba(0, 0, 255, 1)">new</span> OneTimeWorkRequest.Builder(CheckNetworkWorker.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">)
                        .setInitialDelay(</span>30<span style="color: rgba(0, 0, 0, 1)">, TimeUnit.SECONDS)
                        .addTag(TAG)
                        .setBackoffCriteria(BackoffPolicy.LINEAR, </span>1<span style="color: rgba(0, 0, 0, 1)">, TimeUnit.MINUTES)
                        .build();
                mOneRequestId </span>=<span style="color: rgba(0, 0, 0, 1)"> oneRequest.getId();
                WorkManager.getInstance(context).enqueue(oneRequest);</span></pre>
</div>
<p>用tag取消</p>
<div class="cnblogs_code">
<pre>WorkManager.getInstance(context).cancelAllWorkByTag(TAG);</pre>
</div>
<p><strong>另外注意,</strong>在使用getWorkInfosByTagLiveData 进行监听回调时List&lt;WorkInfo&gt;也会有多个,<strong>有点奇怪</strong>,并且无法好像无法删除这个list数量(取消任务也不行)。但是只会返回一次数据。请谨慎使用,我暂时没明白如何使用它。</p>
<div class="cnblogs_code">
<pre>                OneTimeWorkRequest oneTimeWorkRequest = <span style="color: rgba(0, 0, 255, 1)">new</span> OneTimeWorkRequest.Builder(MyWork.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">)
                        .setInitialDelay(</span>2, TimeUnit.SECONDS)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置初始延时时间</span>
                        .addTag("tag1")<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">添加TAG</span>
<span style="color: rgba(0, 0, 0, 1)">                        .build();
                WorkManager.getInstance(MainActivity.</span><span style="color: rgba(0, 0, 255, 1)">this</span>).getWorkInfosByTagLiveData("tag1").observe(MainActivity.<span style="color: rgba(0, 0, 255, 1)">this</span>, <span style="color: rgba(0, 0, 255, 1)">new</span> Observer&lt;List&lt;WorkInfo&gt;&gt;<span style="color: rgba(0, 0, 0, 1)">() {
                  @Override
                  </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> onChanged(List&lt;WorkInfo&gt;<span style="color: rgba(0, 0, 0, 1)"> workInfos) {
                        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (workInfos == <span style="color: rgba(0, 0, 255, 1)">null</span> &amp;&amp;<span style="color: rgba(0, 0, 0, 1)"> workInfos.isEmpty()) {
                            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
                        }
                        Log.e(</span>"调试_临时_log", "this_ workInfos.size = " +<span style="color: rgba(0, 0, 0, 1)"> workInfos.size());
                        WorkInfo workInfo </span>= workInfos.get(0<span style="color: rgba(0, 0, 0, 1)">);
                        </span><span style="color: rgba(0, 0, 255, 1)">switch</span><span style="color: rgba(0, 0, 0, 1)"> (workInfo.getState()) {
                            </span><span style="color: rgba(0, 0, 255, 1)">case</span><span style="color: rgba(0, 0, 0, 1)"> RUNNING:
                              Log.e(</span>"调试_临时_log", "this_进行中"<span style="color: rgba(0, 0, 0, 1)">);
                              </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
                            </span><span style="color: rgba(0, 0, 255, 1)">case</span><span style="color: rgba(0, 0, 0, 1)"> CANCELLED:
                              Log.e(</span>"调试_临时_log", "this_取消"<span style="color: rgba(0, 0, 0, 1)">);
                              </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
                            </span><span style="color: rgba(0, 0, 255, 1)">case</span><span style="color: rgba(0, 0, 0, 1)"> SUCCEEDED:
                              Log.e(</span>"调试_临时_log", "this_成功"<span style="color: rgba(0, 0, 0, 1)">);
                              </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
                        }
                  }
                });
                WorkManager.getInstance(MainActivity.</span><span style="color: rgba(0, 0, 255, 1)">this</span>).enqueue(oneTimeWorkRequest);</pre>
</div>
<p><strong>设置任务的结果保存时间&nbsp;<span style="color: rgba(0, 0, 0, 1)">keepResultsForAtLeast</span></strong></p>
<div class="cnblogs_code">
<pre>                oneTimeWorkRequest = <span style="color: rgba(0, 0, 255, 1)">new</span> OneTimeWorkRequest.Builder(MyWork.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">)
                        .keepResultsForAtLeast(</span>10, TimeUnit.MINUTES)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">结果延迟保存</span>
                        .build();</pre>
</div>
<p><strong>设置退避策略 <span style="color: rgba(0, 0, 0, 1)">setBackoffCriteria</span></strong></p>
<p><span style="color: rgba(0, 0, 0, 1)">一般当我们任务执行失败的时候任务需要重试的时候会用到这个函数,在任务执行失败的时候Worker类的doWork()函数返回Result.RETRY告诉这个任务要重试。那重试的策略就是通过setBackoffCriteria()函数来设置的。</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">BackoffPolicy有两个值:</span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">BackoffPolicy</span>.LINEAR(每次重试的时间线性增加,比如第一次10分钟,第二次就是20分钟)</span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">BackoffPolicy</span>.EXPONENTIAL(每次重试时间指数增加)。</span><strong><span style="color: rgba(0, 0, 0, 1)"> <br></span></strong></p>
<div class="cnblogs_code">
<pre>                oneTimeWorkRequest = <span style="color: rgba(0, 0, 255, 1)">new</span> OneTimeWorkRequest.Builder(MyWork.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">)
                        .setBackoffCriteria(BackoffPolicy.LINEAR, </span>10,TimeUnit.MINUTES)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">退避策略 线性增加 10分钟重试</span>
                        .build(); </pre>
</div>
<h2>PeriodicWorkRequest</h2>
<p>因为前面没有说明过PeriodicWorkRequest,所以这里说明下PeriodicWorkRequest创建的一些细节。首先Builder(MyWork.<span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)">class</span>, <span style="color: rgba(0, 0, 0, 1)">15</span><span style="color: rgba(0, 0, 0, 1)"> ,TimeUnit.MINUTES)</span></span> 三个参数,第二个参数是重复触发的时间,第三个参数是单位。</p>
<p><strong>请注意</strong>,这里的重复周期时间是有要求的,大于等于15分钟,这个在Builder方法的注释里有说明PeriodicWorkRequest.<span style="color: rgba(102, 14, 122, 1); font-weight: bold; font-style: italic">MIN_PERIODIC_INTERVAL_MILLIS</span><span style="color: rgba(0, 0, 0, 1)">最小间隔时间。</span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><strong>请再次注意</strong>,PeriodicWorkRequest在给<span style="color: rgba(0, 0, 0, 1)">WorkManager</span>入队后就会立马执行,所以你如果需要一开始就延迟需要自行设延迟时间。</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">另外PeriodicWorkRequest的可以设置的属性与OneTimeWorkRequest一致。可以参考上面的说明,这里就不在重复。</span></p>
<div class="cnblogs_code">
<pre>                PeriodicWorkRequest periodicWorkRequest = <span style="color: rgba(0, 0, 255, 1)">new</span> PeriodicWorkRequest.Builder(MyWork.<span style="color: rgba(0, 0, 255, 1)">class</span>, 15<span style="color: rgba(0, 0, 0, 1)"> ,TimeUnit.MINUTES)
                        .build();
                WorkManager.getInstance(MainActivity.</span><span style="color: rgba(0, 0, 255, 1)">this</span>).enqueue(periodicWorkRequest);</pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">约束条件Constraints</span></h1>
<div class="cnblogs_code">
<pre>                Constraints constraints = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Constraints.Builder()
                        .setRequiresDeviceIdle(</span><span style="color: rgba(0, 0, 255, 1)">true</span>)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">触发时设备是否为空闲</span>
                        .setRequiresCharging(<span style="color: rgba(0, 0, 255, 1)">true</span>)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">触发时设备是否充电</span>
                        .setRequiredNetworkType(NetworkType.UNMETERED)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">触发时网络状态</span>
                        .setRequiresBatteryNotLow(<span style="color: rgba(0, 0, 255, 1)">true</span>)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">指定设备电池是否不应低于临界阈值</span>
                        .setRequiresStorageNotLow(<span style="color: rgba(0, 0, 255, 1)">true</span>)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">指定设备可用存储是否不应低于临界阈值</span>
                        .addContentUriTrigger(myUri,<span style="color: rgba(0, 0, 255, 1)">false</span>)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">指定内容{@link android.net.Uri}时是否应该运行{@link WorkRequest}更新</span>
<span style="color: rgba(0, 0, 0, 1)">                        .build();
                OneTimeWorkRequest oneTimeWorkRequest </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> OneTimeWorkRequest.Builder(MyWork.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">)
                        .setConstraints(constraints)
                        .build();
                WorkManager.getInstance(MainActivity.</span><span style="color: rgba(0, 0, 255, 1)">this</span>).enqueue(oneTimeWorkRequest);</pre>
</div>
<p>网络状态条件</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">enum</span><span style="color: rgba(0, 0, 0, 1)"> NetworkType {

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   *这项工作不需要网络
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    NOT_REQUIRED,

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 这项工作需要任何有效的网络连接
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    CONNECTED,

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 这项工作需要未计量的网络连接
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    UNMETERED,

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 此项工作需要非漫游网络连接
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    NOT_ROAMING,

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 此项工作需要计量网络连接
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    METERED
}</span></pre>
</div>
<h1>&nbsp;</h1>
<h1><span style="color: rgba(0, 128, 128, 1)">任务入队</span></h1>
<div class="cnblogs_code">
<pre>WorkManager.getInstance(MainActivity.<span style="color: rgba(0, 0, 255, 1)">this</span>).enqueue(oneTimeWorkRequest);</pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">取消指定ID任务</span></h1>
<div class="cnblogs_code">
<pre>WorkManager.getInstance(MainActivity.<span style="color: rgba(0, 0, 255, 1)">this</span>).cancelWorkById(oneTimeWorkRequest.getId());</pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">取消全部任务</span></h1>
<div class="cnblogs_code">
<pre>WorkManager.getInstance(MainActivity.<span style="color: rgba(0, 0, 255, 1)">this</span>).cancelAllWork();</pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">创建唯一任务</span></h1>
<div class="cnblogs_code">
<pre>WorkManager.getInstance(MainActivity.<span style="color: rgba(0, 0, 255, 1)">this</span>).beginUniqueWork("unique", ExistingWorkPolicy.REPLACE, oneTimeWorkRequest).enqueue();</pre>
</div>
<p>或者</p>
<div class="cnblogs_code">
<pre>WorkManager.getInstance(MainActivity.<span style="color: rgba(0, 0, 255, 1)">this</span>).enqueueUniqueWork("unique", ExistingWorkPolicy.REPLACE, oneTimeWorkRequest);</pre>
</div>
<p>任务类型说明</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">enum</span><span style="color: rgba(0, 0, 0, 1)"> ExistingWorkPolicy {

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
      如果存在具有相同唯一名称的待处理(未完成)任务,请取消并删除它。然后,插入新指定的任务
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    REPLACE,

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 如果存在具有相同唯一名称的待处理(未完成)任务,则不执行任何操作。 否则,插入新指定的任务。
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    KEEP,

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 如果存在具有相同唯一名称的待处理(未完成)任务,请将*新指定的任务作为该任务序列所有叶子的子项附加。否则,请插入*新指定的任务作为新序列的开始。
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    APPEND
}</span></pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">监听唯一任务</span></h1>
<div class="cnblogs_code">
<pre>                WorkManager.getInstance(MainActivity.<span style="color: rgba(0, 0, 255, 1)">this</span>).getWorkInfosForUniqueWorkLiveData("unique").observe(MainActivity.<span style="color: rgba(0, 0, 255, 1)">this</span>, <span style="color: rgba(0, 0, 255, 1)">new</span> Observer&lt;List&lt;WorkInfo&gt;&gt;<span style="color: rgba(0, 0, 0, 1)">() {
                  @Override
                  </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> onChanged(List&lt;WorkInfo&gt;<span style="color: rgba(0, 0, 0, 1)"> workInfos) {

                  }
                });</span></pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">链式任务</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)"><strong><span style="color: rgba(255, 0, 0, 1)">请注意!&nbsp;</span></strong>在任务链中的某个Work执行返回&nbsp;&nbsp;Result.failure() ,那么剩下的任务都不会执行了</span></p>
<p>&nbsp;</p>
<p><span style="color: rgba(0, 128, 128, 1)">代码:</span></p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> fun initListener() {
      btn1.setOnClickListener {
            val data </span>=<span style="color: rgba(0, 0, 0, 1)"> Data.Builder()
                  .putString(</span>"data","初始数据"<span style="color: rgba(0, 0, 0, 1)">)
                  .build()
            val aWorkRequest </span>= OneTimeWorkRequest.Builder(AWork::<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">.java)
                  .setInitialDelay(</span>5<span style="color: rgba(0, 0, 0, 1)">, TimeUnit.SECONDS)
                  .addTag(</span>"zh"<span style="color: rgba(0, 0, 0, 1)">)
                  .setInputData(data)
                  .build()

            val bWorkRequest </span>= OneTimeWorkRequest.Builder(BWork::<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">.java)
                  .setInitialDelay(</span>5<span style="color: rgba(0, 0, 0, 1)">, TimeUnit.SECONDS)
                  .addTag(</span>"zh"<span style="color: rgba(0, 0, 0, 1)">)
                  .build()

            val cWorkRequest </span>= OneTimeWorkRequest.Builder(CWork::<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">.java)
                  .setInitialDelay(</span>5<span style="color: rgba(0, 0, 0, 1)">, TimeUnit.SECONDS)
                  .addTag(</span>"zh"<span style="color: rgba(0, 0, 0, 1)">)
                  .build()
            </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
             * 按顺序执行work, 首先执行用beginWith添加的work然后在执行按then顺序添加的work
             </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
            WorkManager.getInstance(</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">)
                  .beginWith(aWorkRequest)    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">首先</span>
                  .then(bWorkRequest)         <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">然后</span>
<span style="color: rgba(0, 0, 0, 1)">                  .then(cWorkRequest)
                  .enqueue()
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> AWork(@NonNull context: Context, @NonNull workerParams: WorkerParameters) : Worker(context, workerParams) {

      override fun doWork(): Result {
            </span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">
                接收外部传入的数据
             </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
            Log.e(</span>"zh", "AWork doWork 传入数据 = ${inputData.getString("data")}"<span style="color: rgba(0, 0, 0, 1)">)
            </span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">
                将数据传给下一个work
             </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
            val data </span>=<span style="color: rgba(0, 0, 0, 1)"> Data.Builder()
                  .putString(</span>"type","a"<span style="color: rgba(0, 0, 0, 1)">)
                  .build()
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Result.success(data)
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> BWork(@NonNull context: Context, @NonNull workerParams: WorkerParameters) : Worker(context, workerParams) {

      override fun doWork(): Result {
            </span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">
                接收上一个work数据
             </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
            Log.e(</span>"zh", "BWork doWork 上个work传入数据 = ${inputData.getString("type")}"<span style="color: rgba(0, 0, 0, 1)">)
            val data </span>=<span style="color: rgba(0, 0, 0, 1)"> Data.Builder()
                  .putString(</span>"type","b"<span style="color: rgba(0, 0, 0, 1)">)
                  .build()
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Result.success(data)
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> CWork(@NonNull context: Context, @NonNull workerParams: WorkerParameters) : Worker(context, workerParams) {

      override fun doWork(): Result {
            Log.e(</span>"zh", "CWork doWork 上个work传入数据 = ${inputData.getString("type")}"<span style="color: rgba(0, 0, 0, 1)">)
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Result.success()
      }
    }</span></pre>
</div>
<p>结果:</p>
<div class="cnblogs_code">
<pre>2022-03-03 11:21:59.786 8651-8705/com.example.myapplication E/zh: AWork doWork 传入数据 =<span style="color: rgba(0, 0, 0, 1)"> 初始数据
</span>2022-03-03 11:22:04.873 8651-8707/com.example.myapplication E/zh: BWork doWork 上个work传入数据 =<span style="color: rgba(0, 0, 0, 1)"> a
</span>2022-03-03 11:22:10.035 8651-8710/com.example.myapplication E/zh: CWork doWork 上个work传入数据 = b</pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">异步链式任务</span></h1>
<p><strong>&nbsp;一些需要注意的点:</strong></p>
<p>1.这种组合式的异步链式任务,在最后一个任务(下面的代码是FruitWork),会无法从前面2个异步任务里传入值(按理说是应该有传值办法的,个人还在研究中)</p>
<p>2.关于延迟时间, 如果你在相同位置的2个异步任务里都添加了&nbsp;setInitialDelay(2, TimeUnit.SECONDS). 这个属性, 不管里面添加的数值是多少时间, 都会以最大的时间触发, 比如下面代码中的&nbsp;AppleWork 设置了2秒延迟,&nbsp;ApricotWork 设置了5秒延迟. 实际上AppleWork 的延迟也会变成5秒(变成2个任务差不多同步执行). 但是如果你其中一个不设置 setInitialDelay() 那么2个work就会有错开时间的效果. 比如下面的BananaWork 与&nbsp;BlueberryWork. 所以,如果你非要有异步,建议你在doWork直接写线程睡眠</p>
<p>代码</p>
<div class="cnblogs_code">
<pre>    @SuppressLint("EnqueueWork"<span style="color: rgba(0, 0, 0, 1)">)
    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> fun initListener() {
      btn1.setOnClickListener {
            val apple </span>= OneTimeWorkRequest.Builder(AppleWork::<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">.java)
                  .setInitialDelay(</span>2<span style="color: rgba(0, 0, 0, 1)">, TimeUnit.SECONDS)
                  .addTag(</span>"fruit"<span style="color: rgba(0, 0, 0, 1)">)
                  .build()

            val banana </span>= OneTimeWorkRequest.Builder(BananaWork::<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">.java)
                  .addTag(</span>"fruit"<span style="color: rgba(0, 0, 0, 1)">)
                  .build()

            val apricot </span>= OneTimeWorkRequest.Builder(ApricotWork::<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">.java)
                  .setInitialDelay(</span>5<span style="color: rgba(0, 0, 0, 1)">, TimeUnit.SECONDS)
                  .addTag(</span>"fruit"<span style="color: rgba(0, 0, 0, 1)">)
                  .build()

            val blueberry </span>= OneTimeWorkRequest.Builder(BlueberryWork::<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">.java)
                  .setInitialDelay(</span>5<span style="color: rgba(0, 0, 0, 1)">, TimeUnit.SECONDS)
                  .addTag(</span>"fruit"<span style="color: rgba(0, 0, 0, 1)">)
                  .build()

            val fruit </span>= OneTimeWorkRequest.Builder(FruitWork::<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">.java)
                  .setInitialDelay(</span>1<span style="color: rgba(0, 0, 0, 1)">, TimeUnit.SECONDS)
                  .addTag(</span>"fruit"<span style="color: rgba(0, 0, 0, 1)">)
                  .build()

            val workContinuation1: WorkContinuation </span>= WorkManager.getInstance(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">)
                  .beginWith(apple)
                  .then(banana)

            val workContinuation2: WorkContinuation </span>= WorkManager.getInstance(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">)
                  .beginWith(apricot)
                  .then(blueberry)

            WorkContinuation.combine(arrayListOf(workContinuation1, workContinuation2)).then(fruit).enqueue()
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> AppleWork(@NonNull context: Context, @NonNull workerParams: WorkerParameters) : Worker(context, workerParams) {

      override fun doWork(): Result {
            Log.e(</span>"zh", "AppleWork doWork"<span style="color: rgba(0, 0, 0, 1)">)
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Result.success()
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> BananaWork(@NonNull context: Context, @NonNull workerParams: WorkerParameters) : Worker(context, workerParams) {

      override fun doWork(): Result {
            Log.e(</span>"zh", "BananaWork doWork"<span style="color: rgba(0, 0, 0, 1)">)
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Result.success()
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ApricotWork(@NonNull context: Context, @NonNull workerParams: WorkerParameters) : Worker(context, workerParams) {

      override fun doWork(): Result {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">            Thread.sleep(2000)</span>
            Log.e("zh", "ApricotWork doWork"<span style="color: rgba(0, 0, 0, 1)">)
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Result.success()
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> BlueberryWork(@NonNull context: Context, @NonNull workerParams: WorkerParameters) : Worker(context, workerParams) {

      override fun doWork(): Result {
            Log.e(</span>"zh", "BlueberryWork doWork"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">            Thread.sleep(2000)</span>
            <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Result.success()
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> FruitWork(@NonNull context: Context, @NonNull workerParams: WorkerParameters) : Worker(context, workerParams) {

      override fun doWork(): Result {
            Log.e(</span>"zh", "FruitWork doWork"<span style="color: rgba(0, 0, 0, 1)">)
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Result.success()
      }
    }</span></pre>
</div>
<p>结果:</p>
<div class="cnblogs_code">
<pre>2022-03-03 15:27:40.507 15181-15225/com.example.myapplication E/<span style="color: rgba(0, 0, 0, 1)">zh: ApricotWork doWork
</span>2022-03-03 15:27:40.535 15181-15226/com.example.myapplication E/<span style="color: rgba(0, 0, 0, 1)">zh: AppleWork doWork
</span>2022-03-03 15:27:40.678 15181-15229/com.example.myapplication E/<span style="color: rgba(0, 0, 0, 1)">zh: BananaWork doWork
</span>2022-03-03 15:27:45.617 15181-15225/com.example.myapplication E/<span style="color: rgba(0, 0, 0, 1)">zh: BlueberryWork doWork
</span>2022-03-03 15:27:50.818 15181-15229/com.example.myapplication E/zh: FruitWork doWork</pre>
</div>
<p>&nbsp;</p>
<p>End</p>

</div>
<div id="MySignature" role="contentinfo">
    <div style="text-align: center">
    <p style="color:orange;font-size:16px;" >本文来自博客园,作者:观心静 ,转载请注明原文链接:https://www.cnblogs.com/guanxinjing/p/13278814.html </p>
    <div style="color:orange;font-size:16px;">本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。 </div>
</div><br><br>
来源:https://www.cnblogs.com/guanxinjing/p/13278814.html
頁: [1]
查看完整版本: Android开发 WorkManager详解