zoukankan      html  css  js  c++  java
  • 一手遮天 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

  • 相关阅读:
    解决Android Studio和Android SDK Manager无法在线更新的问题[转]
    Git 推送和删除标签
    使用adbWireless无线调试Android真机设备[转]
    Android模拟器对应的电脑快捷键说明
    Windows下用cmd命令安装及卸载服务[转]
    重置SQLSERVER表的自增列,让自增列重新计数【转】
    解决“SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATEMENT 'OpenRowset/OpenDatasource' 的访问……”【转】
    网页编辑器CKEditor4.3.1+CKFinder2.4+JW Player6.7(视频播放器)集成
    JW Player 6.7(网页视频播放器,可在手机中播放),自定义Logo和右键菜单链接,支持MP3、MP4、FLV等格式,支持通过HTML5、FLash播放
    Sqlserver列出所有数据库名,表名,字段名【转】
  • 原文地址:https://www.cnblogs.com/webabcd/p/android_service_WorkerManagerDemo1.html
Copyright © 2011-2022 走看看