Android使用Kotlin API实践WorkManager

WorkManager 提供了一系列 API 可以更加便捷地规划异步任务,即使在应用被关闭之后或者设备重启之后,仍然需要保证立即执行的或者推迟执行的任务被正常处理。对于 Kotlin 开发者,WorkManager 为协程提供了最佳的支持。在本文中,我将通过实践 WorkManager codelab 为大家展示 WorkManager 中与协程相关的基本操作。那么让我们开始吧!

WorkManager 基础

当您需要某个任务保持运行状态,即使用户切换到别的界面或者用户将应用切换到后台,甚至设备重启的时候仍然不影响任务状态,那么非常推荐使用 WorkManager。类似的应用场景包括:

  • 上传日志或者报告数据
  • 使用滤镜处理图片的同时保存图片
  • 通过网络定期同步本地数据

如果您的即时任务可以在用户脱离某个作用域时结束,比如切换到其它界面,我们建议您还是直接使用 Kotlin 协程。

在这个 WorkManager codelab 教程中,我们会对图片进行模糊化处理,并且将处理后的数据存储在磁盘上。我们看一下这个过程中需要哪些操作。

添加 work-runtime-ktx 依赖:

// 获取最新的版本号  https://developer.android.google.cn/jetpack/androidx/releases/work
def work_version = "2.5.0"
implementation "androidx.work:work-runtime-ktx:$work_version"

首先实现我们自己的 Worker 类。我们会在这里实现真正需要在后台执行业务的代码。您可以扩展 Worker 类,并且复写 doWork() 方法。由于这个类非常重要,我们会在后边内容中进行详细介绍。这里是它最初的实现代码。

/* Copyright 2020 Google LLC.
   SPDX-License-Identifier: Apache-2.0 */

class BlurWorker(ctx: Context, params: WorkerParameters) : Worker(ctx, params) {

    override fun doWork(): Result {
        val resourceUri = inputData.getString(KEY_IMAGE_URI)

        return try {
            if (resourceUri.isNullOrEmpty()) {
                Timber.e("Invalid input uri")
                throw IllegalArgumentException("Invalid input uri")
            }

            val outputData = blurAndWriteImageToFile(resourceUri)
            Result.success(outputData)
        } catch (throwable: Throwable) {
            Timber.e(throwable, "Error applying blur")
            Result.failure()
        }
    }
…
}

接下来,创建我们的 work 请求,在本例中,我们希望整个操作仅运行一次,所以我们使用 OneTimeWorkRequest.Builder,将需要模糊化处理的图片的 Uri 作为参数传入。

Kotlin 小贴士 : 要创建输入数据,我们可以使用 workDataOf 函数,它会帮我们创建数据构建器,并且填充键值对,然后为我们创建数据。

/* Copyright 2020 Google LLC.
   SPDX-License-Identifier: Apache-2.0 */

val blurBuilder = OneTimeWorkRequestBuilder<BlurWorker>()
val data = workDataOf(KEY_IMAGE_URI to imageUri.toString())
blurBuilder.setInputData(data)

我们使用 WorkManager 类将上面所做的工作添加到计划队列并且运行。我们可以提供需要执行的任务和这些任务的限制条件。

/* Copyright 2020 Google LLC.
   SPDX-License-Identifier: Apache-2.0 */

val workManager = WorkManager.getInstance(application)
val continuation = workManager.beginUniqueWork(blurBuilder.build())
// 执行任务
continuation.enqueue()

使 Worker 开始执行任务

当您使用 Worker 的时候,WorkManager 会在后台线程中自动调用 Worker.doWork()。doWork() 返回的 Result 会告知 WorkManager 服务是否成功,如果失败则告知是否需要重试。

Worker.doWork() 属于同步调用 -- 您的后台操作需要以阻塞的方式执行,并且所有任务需要在整个 doWork() 函数结束的时候完成。如果您在 doWork() 里调用异步的 API 然后返回结果,那么您回调函数的执行可能会出现问题。

但是如果我希望进行异步操作怎么办?

我们来将上面的示例操作变得复杂一点,比如我希望在数据库中存储所有进行模糊化处理的文件的 Uri。

所以我创建了:

  • 一个简单的 BlurredImage 实体
  • 一个用于插入和获取图片的 DAO 类
  • 数据库

相关的实现代码请 点击这里

如果您需要执行异步操作,比如在数据库中存储数据或者发起网络请求,在 Kotlin 中,我们推荐使用 CoroutineWorker。

CoroutineWorker 通过使用 Kotlin 协程来执行异步任务。

doWork() 方法是一个 suspend 方法。也就是说我们这里可以调用可挂起的 dao 函数。

/* Copyright 2020 Google LLC.
   SPDX-License-Identifier: Apache-2.0 */

class BlurWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker(ctx, params) {

    override suspend fun doWork(): Result {
        val resourceUri = inputData.getString(KEY_IMAGE_URI)

        return try {
            if (resourceUri.isNullOrEmpty()) {
                Timber.e("Invalid input uri")
                throw IllegalArgumentException("Invalid input uri")
            }

            val outputData = blurAndWriteImageToFile(resourceUri)
            // 将 uri 存储到数据库
           val imageDao = ImagesDatabase.getDatabase(applicationContext).blurredImageDao()
            imageDao.insert(BlurredImage(resourceUri))

            Result.success(outputData)
        } catch (throwable: Throwable) {
            Timber.e(throwable, "Error applying blur")
            Result.failure()
        }
    }
...
}

doWork() 默认使用 Dispatchers.Default。您可以将其替换为您所需的 Dispatcher。在这里,我们不需要这么做,因为 Room 已经将数据插入操作放在另外的 Dispatcher 中完成了。更多相关内容可以参考 Room Kotlin API。

开始使用 CoroutineWorker 来执行异步任务吧,即使用户关闭应用也可以确保任务完成。

如果您希望了解更多关于 WorkManager 的内容,请关注未来的相关文章。在那之前,可以访问我们的 codelab 和文档:

以上就是Android使用Kotlin API实践WorkManager的详细内容,更多关于Android实践WorkManager的资料请关注我们其它相关文章!

(0)

相关推荐

  • 神经网络API、Kotlin支持,那些你必须知道的Android 8.1预览版和Android Studio 3.0新特性

    谷歌2017发布会更新了挺多内容的,而且也发布了AndroidStudio3.0预览版,一些功能先睹为快. 过去的五个月里, Kotlin一直是我们反复谈论的重点.现在要告诉大家的是,Android Studio 3.0可以将Kotlin添加到您的项目中了.最新版本的Android Studio在支持Java 8语言功能上得到了改进,另外一个亮点是,有了用于Gradle 3.0.0的Android插件. 好,下面步入正文. 曾仅用 55 秒发布会的 Android 8.0 Oreo 在时隔两个月

  • Android WorkManager浅谈

    一.原文翻译 WorkManager API 可以很容易的指定可延迟的异步任务.允许你创建任务,并把它交给WorkManager来立即运行或在适当的时间运行.WorkManager根据设备API的级别和应用程序状态等因素来选择适当的方式运行任务.如果WorkManager在应用程序运行时执行你的任务,它会在应用程序进程的新线程中执行.如果应用程序没有运行,WorkManager会根据设备API级别和包含的依赖项选择适当的方式安排后台任务,可能会使用JobScheduler.Firebase Jo

  • Android使用Kotlin API实践WorkManager

    WorkManager 提供了一系列 API 可以更加便捷地规划异步任务,即使在应用被关闭之后或者设备重启之后,仍然需要保证立即执行的或者推迟执行的任务被正常处理.对于 Kotlin 开发者,WorkManager 为协程提供了最佳的支持.在本文中,我将通过实践 WorkManager codelab 为大家展示 WorkManager 中与协程相关的基本操作.那么让我们开始吧! WorkManager 基础 当您需要某个任务保持运行状态,即使用户切换到别的界面或者用户将应用切换到后台,甚至设备

  • Android Jetpack库重要组件WorkManager的使用

    目录 前言 后台处理指南 后台处理面临的挑战 如何选择合适的后台解决方案 WorkManager概述 WorkManager使用 1 声明依赖项 2 自定义一个继承自Worker的类 3 选择worker执行的条件 4 下面贴出自定义worker类的全部源码 5 执行任务的方式 6 取消任务的执行 前言 WorkManager是Jetpack很重要的一个组件: 本篇我们就先来讲讲它是如何使用的,在讲解之前我们先了解关于后台处理的一些痛点 后台处理指南 我们知道每个 Android 应用都有一个主

  • Android结合kotlin使用coroutine的方法实例

    最近入了Android坑,目前还处于疯狂学习的状态,所以很久都没有写博客了.今天记录一个小代码片段,在Android上使用coroutine 的小例子. 由于我自己是做一个记账软件来学习的,我用了gRPC,最开始我是使用线程来做网络请求的: thread { // 网络请求代码 runOnUiThread { // 更新UI的代码 } } 今天把这一套全部重写成用coroutine. 首先coroutine得有个调度器,英文叫做 "Dispatchers",有这么几个: Dispatc

  • Room Kotlin API的使用入门教程

    Room 是 SQLite 的封装,它使 Android 对数据库的操作变得非常简单,也是迄今为止我最喜欢的 Jetpack 库.在本文中我会告诉大家如何使用并且测试 Room Kotlin API,同时在介绍过程中,我也会为大家分享其工作原理. 我们将基于 Room with a view codelab 为大家讲解.这里我们会创建一个存储在数据库的词汇表,然后将它们显示到屏幕上,同时用户还可以向列表中添加单词. 定义数据库表 在我们的数据库中仅有一个表,就是保存词汇的表.Word 类代表表中

  • Android编程视频播放API之MediaPlayer用法示例

    本文实例讲述了Android编程视频播放API之MediaPlayer用法.分享给大家供大家参考,具体如下: 现在项目要做音视频这块功能,这正是我相对比较薄弱的地方,项目中要用到,赶紧抓紧时间学习.前面有一编介绍不错的文章http://www.jb51.net/article/121881.htm,值得学习. 这里给出一个较为简单的示例: /** * Android API MediaPlayer示例 * * @description: * @author ldm * @date 2016-4-

  • Android通过原生APi获取所在位置的经纬度

    在Android开发当中,经常需要用到定位功能,尤其是依赖于地理位置功能的应用,本文介绍了Android通过原生APi获取所在位置的经纬度,分享给大家 一.难点介绍 1.难点 我们的应用要新增一个功能,就是在用户打开附件的人页面后,将用户的经纬度通过一个接口返回给服务端,从而让服务器可以准确定位. 因为只是添加一个小功能所以,引入第三方SDK定位就有些大材小用了,所以就准备借助原生APi:LocationManager来完成. 经过在网络上一搜,有很多关于通过LocationManager获取经

  • android通过google api获取天气信息示例

    android通过google API获取天气信息 复制代码 代码如下: public class WeatherActivity extends Activity { private TextView txCity; private Button btnSearch; private Handler weatherhandler; private Dialog progressDialog; private Timer timer;    /** Called when the activit

  • android通过Location API显示地址信息的实现方法

    本文实例讲述了android通过Location API显示地址信息的实现方法.分享给大家供大家参考.具体如下: android的Locatin API,可以通过Geocoder类,显示具体经纬度的地址信息.如: 通过Geocoder的方法getFromLocation()可以得到Address对象的List.我只取一个Address结果,可以取多个,但是意义不大. StringBuilder builder = new StringBuilder(); builder.append("北纬:&

  • Android中aapt命令实践

    引言 朋友要查看一个已存在包的versionCode信息,在群里面询问,由于是已经存在的apk包,并且只需要其中的versionCode信息,笔者就给发了一段aapt命令:aapt dump badging <files.apk> 下面针对aapt 命令做一下介绍,之前笔者也对一些常用adb命令也做过介绍:总结一些常用Android adb 命令,了解这些命令以后,可以更方便我们开发,提高开发效率.在这笔者在网上随便下载了一个app作为演示用. aapt 命令大全 aapt d[ump] [-

  • Android指纹识别API讲解,一种更快更好的用户体验

    我发现了一个比较怪的现象.在iPhone上使用十分普遍的指纹认证功能,在Android手机上却鲜有APP使用,我简单观察了一下,发现Android手机上基本上只有支付宝.微信和极少APP支持指纹认证功能,就连银行和金融类的应用都基本不支持,甚至很多开发者都不知道Android系统是有指纹认证的官方API的. 事实上,Android从6.0系统开始就支持指纹认证功能了,但是指纹功能还需要有硬件支持才行,而Android手机的硬件都是由各厂商生产的,手机档次也参差不齐,因此不能像iPhone那样保证

随机推荐