Jetpack学习——WorkManager合并任务流

介绍

何时使用WorkManager

WorkManager最适用于可以延迟的任务,即使应用程序或设备重新启动(例如,使用后端服务定期同步数据并上载日志或分析数据),仍然可以运行。

向后兼容性

WorkManager将利用正确的调度API:它在Android 6.0+(API 23+)上使用JobScheduler API,在以前的版本上使用AlarmManager和BroadcastReceiver的组合。

例如,当系统处于打盹模式时,WorkManager将在Android 6.0+(API 23+)设备的维护窗口期间安排后台工作。

可靠的调度

使用WorkManager,可以轻松添加网络可用性或计费状态等约束。任务将在满足约束时运行,并在运行时失败时自动重试。例如,如果任务需要网络可用,则当网络不再可用时将停止该任务,并在以后重试。

不仅如此,它还可以使用LiveData监视工作状态并检索工作结果,这样可以在任务完成时通知您的UI。

  • Worker
    指定需要执行的任务。WorkManager api包含一个抽象的Worker类。我们需要继承并实现这个类

  • WorkRequest
    表示一个独立的任务。一个WorkRequest对象需要至少指定一个执行该任务的Worker类。当然我们也可以添加更多的细节,比如指定任务应该运行的环境等。每一个WorkRequest都有一个自动生成唯一ID,我们可以使用这个ID来执行诸如取消排队任务或者获取任务状态等操作。WorkRequest是一个抽象类,我们可以使用系统提供的子类-OneTimeWorkRequestPeriodicWorkRequest

  • WorkRequest.Builder:
    创建WorkRequest对象的帮助类。同样,我们也需要用系统提供的子类:OneTimeWorkRequest.Builder 或者 PeriodicWorkRequest.Builder。

  • Constraints
    指定任务运行的限制条件(例如,“仅当连接到网络时”)。使用Constraint.Builder来创建Constraints,并在创建WorkRequest之前把Constraints传给WorkRequest.Builder。

  • WorkManager
    对工作请求进行管理。我们需要把WorkRequest对象传给WorkManager以便将任务编入队列。WorkManager以这样的方式调度任务,以分散系统资源的负载,同时满足我们指定的约束条件。

  • WorkStatus
    包含特定任务的信息。WorkManager为每个WorkRequest对象提供一个LiveData。LiveData持有一个WorkStatus对象;通过观察这个LiveData,我们可以确定任务的当前状态,并在任务完成后获得返回值。

使用

现在完成一个demo,功能是先将一张图片进行模糊处理,然后存储到文件中,这里分成两个任务进行

模糊处理任务BlurWorker

public class BlurWorker extends Worker {
    
    public BlurWorker(@NonNull Context appContext, @NonNull WorkerParameters workerParams) {
        super(appContext, workerParams);
    }

    @Override
    public Worker.Result doWork() {

        Context applicationContext = getApplicationContext();
        // 增加时长 用于测试
        WorkerUtils.sleep();

        String resourceUri = getInputData().getString(Constants.KEY_IMAGE_URI);
        try {
            if (TextUtils.isEmpty(resourceUri)) {
                Log.e(TAG, "Invalid input uri");
                throw new IllegalArgumentException("Invalid input uri");
            }

            ContentResolver resolver = applicationContext.getContentResolver();

            // Create a bitmap
            Bitmap bitmap = BitmapFactory.decodeStream(
                    resolver.openInputStream(Uri.parse(resourceUri)));

            // Blur the bitmap
            Bitmap output = WorkerUtils.blurBitmap(bitmap, applicationContext);

            // Write bitmap to a temp file
            Uri outputUri = WorkerUtils.writeBitmapToFile(applicationContext, output);

            // Return the output for the temp file
            Data outputData = new Data.Builder().putString(
                    Constants.KEY_IMAGE_URI, outputUri.toString()).build();

            return Result.success(outputData);
        } catch (FileNotFoundException fileNotFoundException) {
            throw new RuntimeException("Failed to decode input stream", fileNotFoundException);

        } catch (Throwable throwable) {

            // If there were errors, return FAILURE
            Log.e(TAG, "Error applying blur", throwable);
            return Result.failure();
        }
    }
}

存储到磁盘任务SaveImageToFileWorker

public class SaveImageToFileWorker extends Worker {

    public SaveImageToFileWorker(
            @NonNull Context appContext,
            @NonNull WorkerParameters workerParams) {
        super(appContext, workerParams);
    }

    private static final String TITLE = "Blurred Image";
    private static final SimpleDateFormat DATE_FORMATTER =
            new SimpleDateFormat("yyyy.MM.dd 'at' HH:mm:ss z", Locale.getDefault());

    @NonNull
    @Override
    public Worker.Result doWork() {
        Context applicationContext = getApplicationContext();

        ContentResolver resolver = applicationContext.getContentResolver();
        try {
            String resourceUri = getInputData()
                    .getString(Constants.KEY_IMAGE_URI);
            Bitmap bitmap = BitmapFactory.decodeStream(
                    resolver.openInputStream(Uri.parse(resourceUri)));
            // 存到文件
            String imageUrl = MediaStore.Images.Media.insertImage(
                    resolver, bitmap, TITLE, DATE_FORMATTER.format(new Date()));
            if (TextUtils.isEmpty(imageUrl)) {
                return Result.failure();
            }
            // 输出数据
            Data outputData = new Data.Builder()
                    .putString(Constants.KEY_IMAGE_URI, imageUrl)
                    .build();
            return Result.success(outputData);
        } catch (Exception exception) {
            return Result.failure();
        }
    }

调用

 // 模糊任务
 OneTimeWorkRequest.Builder blurBuilder =
                    new OneTimeWorkRequest.Builder(BlurWorker.class);
 // 设置输入数据                  
 blurBuilder.setInputData(createInputDataForUri());

 // 存贮任务
 OneTimeWorkRequest save = new OneTimeWorkRequest.Builder(SaveImageToFileWorker.class)
                .setConstraints(constraints)
                .addTag(TAG_OUTPUT)
                .build();

// Add WorkRequest to Cleanup temporary images    
 WorkContinuation continuation = mWorkManager                   
         .beginUniqueWork(IMAGE_MANIPULATION_WORK_NAME,         
                 ExistingWorkPolicy.REPLACE,                    
                 OneTimeWorkRequest.from(CleanupWorker.class)); 

 continuation = continuation.then(blurBuilder.build()); 
 continuation = continuation.then(save);    
 // Actually start the work
 continuation.enqueue();  

取消任务

// 取消任务
 UUID id = compressionWork.getId();
 WorkManager.getInstance().cancelWorkById(id);

获取状态 和结果

LiveData<WorkInfo> status = WorkManager.getInstance().getWorkInfoByIdLiveData(compressionWork.getId());
        status.observe(activity, new Observer<WorkInfo>() {
            @Override
            public void onChanged(@Nullable WorkInfo workInfo) {
                  // 获取状态
                  boolean finished = workInfo.getState().isFinished();
                  if (!finished) {
                       showWorkInProgress();
                    } else {
                       showWorkFinished();
                   // 获取输出内容
                   Data outputData = workInfo.getOutputData();

                   String outputImageUri =
                        outputData.getString(Constants.KEY_IMAGE_URI);

            }
        });

解析

下回揭晓…

猜你喜欢

转载自blog.csdn.net/u011077027/article/details/92417135