联系我们
简单又实用的WordPress网站制作教学
当前位置:网站首页 > 程序开发学习 > 正文

Kotlin之协程(第七趴)--在高阶函数中使用协程&;and;将协程与工作经理结合使用

作者:访客发布时间:2023-12-13分类:程序开发学习浏览:112


导读:1个、在高阶函数中使用协程您将重构MainViewModel中的refreshTitle、以使用常规的数据加载函数.refreshTitle的当前实现运行正常,但我们可以创建一个始...

1个、在高阶函数中使用协程

您将重构MainViewModel中的refreshTitle、以使用常规的数据加载函数.

refreshTitle的当前实现运行正常,但我们可以创建一个始终显示旋转图标的常规数据加载协程.对于加载数据以影响多个事件且希望确保加载旋转图标始终显示的代码库,这可能非常有用.

查看当前实现,可以发现,除reppository.refreshTitle()之外的每行代码都是显示旋转图标和错误的样板代码.

// MainViewModel.kt
fun refreshTitle() {
    viewModelScope.launch {
        try {
            _spinner.value = true
            // this is the only part that changes between sources
            repository.refreshTitle()
        } catchh (error: TitleRefreshError) {
            _snackBar.value = error.message
        } finally {
            _spinner.value = false
        }
    }
}
重要提示:虽然我们在此代码中仅适用viewModelScope,但通常可以在任何意义的位置添加作用于。如果不再需要它,记得将其取消。

例如,您可以在RecyclerView Adapter中声明一个作用域,以执行DiffUtil操作。

1.1、在高阶函数中使用协程

将以下代码添加到MainViewModel.kt中MainViewModel.kt

private fun launchDataLoad(block: suspend () -> Unit): Job {
    return viewModelScope.launch {
        try {
            _spinner.value = true
            block()
        } catch (error: TitleRefreshError) {
            _snackBar.value = error.message
        } finally {
            _spinner.value = false
        }
    }
}

现在重构refreshTitle()以使用此高阶函数.MainViewModel.kt

fun refreshTitle() {
    launchDataLoad {
        repository.refreshTitle()
    }
}

通过抽象化用于显示加载旋转图标和显示错误的逻辑,我们简化了加载数据所需的实际代码.显示旋转图标或显示错误是易于泛化到任何数据加载的内容,而实际数据源和目标则需要每次都指定.

为了构建此抽象,launchDataLoad接受一个属于挂起Lambda的参数block那就是。挂起Lambda可让您调用挂起函数.Kotlin就是通过这种方式实现我们在此代码中使用的launchrunBlocking协程构建器.

// suspend lambda

block: suspend () -> Unit

要创建挂起Lambda,应从suspend关键字着手.函数的箭头和返回值类型Unit用于完成声明.

您通常不必声明自己的挂起Lambda,但它们可能有助于创建这类封装重复逻辑的抽象!

2个、将协程与工作经理结合使用

本部分,您将学习如何从工作经理使用基于协程的代码。

2.1、什么是工作管理器

安卓有多个选项用于处理可延迟的后台工作。本练习介绍如何将WorkManager与协程集成.工作经理是一个兼容、灵活且简单的库,用于处理可延迟的后台工作。工作经理是安卓中这些用例的推荐解决方案。

工作经理属于安卓Jetpack的一部分,是一种架构组件,用于处理既需要机会性执行,又需要有保证的执行的后台工作。机会性执行意味着工作经理会尽快执行您的后台工作。有保证的执行意味着工作经理会负责通过逻辑保障在各种情况下启动您的工作,即使用户离开您的应用也无妨。

因此,工作经理适合最终必须完成的任务。

以下是一些适合使用工作经理的任务的典型示例:

  • 上传日志
  • 对图片应用滤镜并保存图片
  • 定期将本地数据与网络同步

2.2、将协程与工作经理一起使用

工作经理为不同用例提供其基本ListenableWorker类的不同实现.

最简单的Worker类可让我们通过工作经理执行一些同步操作。不过,根据目前为止我们将代码库转换为使用协程和挂起函数的经验,我们发现使用工作管理器的最好方法是通过CoroutineWorker类,此类支持将doWork()函数定义为挂起函数.

首先,请打开refreshMainDataWork那就是。它已扩展了CoroutineWorker,您需要实现doWork那就是。

suspend doWork函数中,从代码库中调用refreshTitle()并返回响应的结果.

完成TODO后,代码将如下所示.

override suspend fun doWork(): Result {
    val database = getDatabase(applicationContext)
    val repository = TitleRepository(network, database.titleDao)
    
    return try {
        repository.refreshTitle()
        Result.success()
    } catch (error: TitleRefreshError) {
        Result.failure()
    }
}

请注意,CoroutineWorker.doWork()是一个挂起函数.与更简单的Worker类不同,此代码不会在您的工作管理器配置所指定的执行器上运行,而是使用coroutineContext成员的调度程序(默认为Dispatchers.Default)

2.3、测试我们的协作员

工作经理提供了几种不同的Worker类测试方法.

工作管理器v2.1引入了一组新的API来支持更简单的ListenableWorker类测试方法,并最终推出了CoroutineWorker。我们将在代码中使用一个名为TestListenableWorkerBuilder的新接口。

为了添加我们的新测试,更新androidTest文件夹下的RefreshMainWorkTest文件.

此文件的内容为:

package com.example.android.kotlincoroutines.main

import android.content.Context
import androidx.test.core.app.ApplicationProvider
import androidx.work.ListenableWorker.Result
import android.content.Context
import androidx.test.core.app.ApplicationProvider
import androidx.work.ListenableWorker.Result
import androidx.work.testing.TestLiestenableWorkerBuilder
import com.example.android.kotlincoroutines.fakes.MainNetworkFake
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Junit4

@RunWith(JUnit4::class)
class RefreshMainDataWorkTest {

@Test
fun testRefreshMainDataWork() {
    val fakeNetwork = MainNetworkFake("OK")
    
    val context = ApplicationProvider.getApplicationContext<Context>()
    val worker = TestListenableWorkerBuilder<RefreshMainDataWork>(context)
        .setWorkerFactory(RefreshMainDataWork.Factory(fakeNetwork))
        .build()
        
    // Start the work synchronously
    val result = worker.startWork().get()
    
    assertThat(result).isEqualTo(Result.success)
}
}

在执行测试之前,我们会先告知WorkManager关于工厂的信息,以便我们注入虚构网络.

测试本身会使用TestListenableWorkerBuilder创建我们的工作器,然后我们可以运行该工作器来调用startWork()方法.

WorkManager只是用来说明如何使用协程简化接口设计的一个示例。


标签:高阶函数科特林工作经理将协程安培


程序开发学习排行
最近发表
网站分类
标签列表