• 一手遮天 Android


    项目地址 https://github.com/webabcd/AndroidDemo
    作者 webabcd

    一手遮天 Android - 后台服务: WorkerManager

    示例如下:

    /service/WorkerManagerDemo1.java

    /**
     * WorkerManager - 后台任务管理
     *     OneTimeWorkRequest - 一次性任务请求
     *     PeriodicWorkRequest - 周期性任务请求
     *
     * 注:具体的后台任务逻辑请参见 /service/Worker1.java
     */
    
    package com.webabcd.androiddemo.service;
    
    import androidx.annotation.RequiresApi;
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.lifecycle.Observer;
    import androidx.work.BackoffPolicy;
    import androidx.work.Constraints;
    import androidx.work.Data;
    import androidx.work.NetworkType;
    import androidx.work.OneTimeWorkRequest;
    import androidx.work.PeriodicWorkRequest;
    import androidx.work.WorkContinuation;
    import androidx.work.WorkInfo;
    import androidx.work.WorkManager;
    
    import android.os.Build;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    
    import com.webabcd.androiddemo.R;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Locale;
    import java.util.UUID;
    import java.util.concurrent.TimeUnit;
    
    @RequiresApi(api = Build.VERSION_CODES.M)
    public class WorkerManagerDemo1 extends AppCompatActivity {
    
        private final String LOG_TAG = "WorkerManagerDemo1";
    
        private UUID mId;
    
        private Button mButton1;
        private Button mButton2;
        private TextView mTextView1;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_service_workermanagerdemo1);
    
            mButton1 = findViewById(R.id.button1);
            mButton2 = findViewById(R.id.button2);
            mTextView1 = findViewById(R.id.textView1);
    
            sample();
        }
    
        private void sample() {
            mButton1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    addTask();
                }
            });
    
            mButton2.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    removeTask();
                }
            });
        }
    
        // 新增任务
        private void addTask() {
            // 构造 Constraints 对象,用于指定任务触发的约束条件
            Constraints constraints = new Constraints.Builder()
                    .setRequiresCharging(false) // 是否需要处于充电状态
                    .setRequiredNetworkType(NetworkType.NOT_REQUIRED) // 是否需要处于网络连接状态
                    .setRequiresBatteryNotLow(false) // 是否需要处于非低电量状态
                    .setRequiresDeviceIdle(false) // 是否需要处于系统空闲状态(api level 23 或以上)
                    .build();
    
            // 构造需要传递给 Worker 的数据
            Data inputData = new Data.Builder()
                    .putString("input_param1", "input_value1")
                    .putString("input_param2", "input_value2")
                    .build();
    
            // OneTimeWorkRequest - 一次性任务请求(继承自 WorkRequest)
            // 需要指定自定义 Worker 类
            OneTimeWorkRequest oneTimeWorkRequest = new OneTimeWorkRequest.Builder(Worker1.class)
                    // 设置任务的触发条件
                    .setConstraints(constraints)
                    // 指定需要传递给 Worker 的数据
                    .setInputData(inputData)
                    // 如果符合触发条件,则在 10 秒后执行任务(我这里测试,这个值最小是 5 秒)
                    .setInitialDelay(10, TimeUnit.SECONDS)
                    // Worker 发生异常或在 doWork() 中返回 Result.retry() 时的自定义重试策略
                    // 下面的代码代表重试间隔为:重试次数 * 15 秒(我这里测试,这个值最小是 10 秒)
                    .setBackoffCriteria(BackoffPolicy.LINEAR,15, TimeUnit.SECONDS)
                    // 指定任务的标签(分组用,多个任务可以指定相同的标签),后续可以通过标签获取任务状态或取消任务
                    .addTag("myTag")
                    .build();
    
            // PeriodicWorkRequest - 周期性任务请求(继承自 WorkRequest)
            // 需要指定自定义 Worker 类
            // 执行间隔最小为 15 分钟
            PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest.Builder(Worker1.class, 15, TimeUnit.MINUTES).build();
    
            // 将任务请求加入 WorkManager 队列
            // 也可以传入一个任务请求集合,他们会并行执行
            WorkManager.getInstance(this).enqueue(oneTimeWorkRequest);
    
    
            // 如果有一系列任务需要按顺序执行,则可以通过 beginWith().then().then()...enqueue() 实现
            // 以下代码用于实现:先执行 A,执行完成后再执行 B,执行完成后再执行 C
            // WorkManager.getInstance(this).beginWith(WorkRequestA).then(WorkRequestB).then(WorkRequestC).enqueue();
    
            // 如果将任务请求集合传入 beginWith() 或 then() 则他们会并行执行
            // 以下代码用于实现:A 和 B 并行执行,当他们都执行完成后再执行 C
            // List<OneTimeWorkRequest> taskList = new ArrayList<>();
            // taskList.add(WorkRequestA);
            // taskList.add(WorkRequestB);
            // WorkManager.getInstance(this).beginWith(taskList).then(WorkRequestC).enqueue();
    
            // 关于任务顺序的更复杂的需求,可能会需要用到 combine() 方法
            // 以下代码用于实现:
            //   1、先执行 A,执行完成后再执行 B
            //   2、先执行 C,执行完成后再执行 D
            //   3、AB 和 CD 可以并行执行
            //   4、AB 和 CD 都执行完成后再执行 E
            /*
            WorkContinuation workContinuation1 =  WorkManager.getInstance(this).beginWith(WorkRequestA).then(WorkRequestB);
            WorkContinuation workContinuation2 =  WorkManager.getInstance(this).beginWith(WorkRequestC).then(WorkRequestD);
            List<WorkContinuation> taskList = new ArrayList<>();
            taskList.add(workContinuation1);
            taskList.add(workContinuation2);
            WorkContinuation.combine(taskList).then(WorkRequestE).enqueue();
            */
    
    
            // 通过 WorkRequest 的 getId() 可以获取到这个任务的标识,后续可以通过此标识获取该任务状态或取消该任务
            mId = oneTimeWorkRequest.getId();
            Log.d(LOG_TAG, String.format("add OneTimeWorkRequest, id:%s, threadId:%d", mId, Thread.currentThread().getId()));
    
            // 获取任务状态
            loadTaskStatus();
        }
    
        // 删除当前的任务
        private void removeTask() {
            // 根据 id 删除任务
            WorkManager.getInstance(this).cancelWorkById(mId);
            // 根据 tag 删除任务
            // WorkManager.getInstance(this).cancelAllWorkByTag(tag);
            // 取消全部任务
            // WorkManager.getInstance(this).cancelAllWork();
        }
    
        // 获取任务状态
        private void loadTaskStatus() {
            try {
                // 根据 id 获取任务信息
                // List<WorkInfo> workInfoList = WorkManager.getInstance(this).getWorkInfoById(mId).get();
                // 根据 tag 获取任务信息
                // List<WorkInfo> workInfoList = WorkManager.getInstance(this).getWorkInfosByTag(tag).get();
    
                // 监控指定 tag 的任务的状态变化
                // WorkManager.getInstance(this).getWorkInfosByTagLiveData(tag).observe();
                // 监控指定 id 的任务的状态变化
                WorkManager.getInstance(this).getWorkInfoByIdLiveData(mId).observe(WorkerManagerDemo1.this, new Observer<WorkInfo>()
                {
                    @Override
                    public void onChanged(WorkInfo workInfo)
                    {
                        // 获取通过 Work 的 doWork() 的 Result.success() 或 Result.failure 设置的数据
                        Data outputData = workInfo.getOutputData();
    
                        // 任务状态(可能的值有:ENQUEUED, RUNNING, SUCCEEDED, FAILED, BLOCKED, CANCELLED)
                        WorkInfo.State state = workInfo.getState();
    
                        writeMessage(String.format(Locale.US, "Worker id:%s
    output_param1:%s
    output_param2:%s
    state:%s
    threadId:%d",
                                workInfo.getId(),
                                outputData.getString("output_param1"), outputData.getString("output_param2"),
                                state.name(),
                                Thread.currentThread().getId()));
                    }
                });
    
            } catch (Exception ex) {
                Log.e(LOG_TAG, ex.toString());
            }
        }
    
        private void writeMessage(final String message) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mTextView1.setText(message);
                }
            });
        }
    }
    

    /layout/activity_service_workermanagerdemo1.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <Button
            android:id="@+id/button1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="新增任务" />
    
        <Button
            android:id="@+id/button2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="删除当前的任务" />
    
        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    
    </LinearLayout>
    

    项目地址 https://github.com/webabcd/AndroidDemo
    作者 webabcd

  • 相关阅读:
    bzoj千题计划174:bzoj1800: [Ahoi2009]fly 飞行棋
    bzoj千题计划173:bzoj1257: [CQOI2007]余数之和sum
    bzoj千题计划172:bzoj1192: [HNOI2006]鬼谷子的钱袋
    bzoj千题计划171:bzoj2456: mode
    bzoj千题计划170:bzoj1968: [Ahoi2005]COMMON 约数研究
    bzoj千题计划169:bzoj2463: [中山市选2009]谁能赢呢?
    bzoj千题计划168:bzoj3513: [MUTC2013]idiots
    oracle 11g RAC 的一些基本概念(四)
    fdisk用法(转载)
    Oracle 11g 新特性 -- Oracle Restart 说明(转载)
  • 原文地址:https://www.cnblogs.com/webabcd/p/android_service_WorkerManagerDemo1.html
Copyright © 2020-2023  润新知