android - 如何在 Kotlin 中将 Fuel 与协程一起使用?

标签 android kotlin kotlin-coroutines

我想获取 API 请求并将请求的数据保存到数据库中。还想返回数据(即写入数据库)。我知道,这在 RxJava 中是可能的,但现在我在 Kotlin 协程中编写,目前使用 Fuel 而不是 Retrofit(但差异不是很大)。我读了How to use Fuel with a Kotlin coroutine ,但不明白。

如何编写协程和方法?

更新

比如说,我们有一个 Java 和 Retrofit,RxJava。然后我们就可以写代码了。

区域响应:

@AutoValue
public abstract class RegionResponse {
    @SerializedName("id")
    public abstract Integer id;
    @SerializedName("name")
    public abstract String name;
    @SerializedName("countryId")
    public abstract Integer countryId();

    public static RegionResponse create(int id, String name, int countryId) {
        ....
    }
    ...
}

地区:

data class Region(
    val id: Int,
    val name: String,
    val countryId: Int)

网络:

public Single<List<RegionResponse>> getRegions() {
    return api.getRegions();
    // @GET("/regions")
    // Single<List<RegionResponse>> getRegions();
}

区域库:

fun getRegion(countryId: Int): Single<Region> {
    val dbSource = db.getRegion(countryId)
    val lazyApiSource = Single.defer { api.regions }
            .flattenAsFlowable { it }
            .map { apiMapper.map(it) }
            .toList()
            .doOnSuccess { db.updateRegions(it) }
            .flattenAsFlowable { it }
            .filter({ it.countryId == countryId })
            .singleOrError()
    return dbSource
            .map { dbMapper.map(it) }
            .switchIfEmpty(lazyApiSource)
}

区域交互器:

class RegionInteractor(
    private val repo: RegionRepository,
    private val prefsRepository: PrefsRepository) {

    fun getRegion(): Single<Region> {
        return Single.fromCallable { prefsRepository.countryId }
                .flatMap { repo.getRegion(it) }
                .subscribeOn(Schedulers.io())
    }
}

最佳答案

我们一层一层的看。

首先,据我所知,您的 RegionResponseRegion 完全适合这个用例,所以我们根本不会碰它们。

您的网络层是用 Java 编写的,因此我们假设它始终需要同步行为,并且也不会触及它。

所以,我们从代码库开始:

fun getRegion(countryId: Int) = async {
    val regionFromDb = db.getRegion(countryId)

    if (regionFromDb == null) {
        return apiMapper.map(api.regions).
                  filter({ it.countryId == countryId }).
                  first().
           also {
           db.updateRegions(it)
        }
    }

    return dbMapper.map(regionFromDb)
}

请记住,我没有您的代码,因此细节可能会有所不同。但是协程的一般想法是,你用 async() 启动它们,以防它们需要返回结果,然后编写你的代码,就好像你在一个完美的世界里,而你不需要需要关心自己的并发性。

现在是交互者:

class RegionInteractor(
    private val repo: RegionRepository,
    private val prefsRepository: PrefsRepository) {

    fun getRegion() = withContext(Schedulers.io().asCoroutineDispatcher()) {
        val countryId = prefsRepository.countryId
        return repo.getRegion(countryId).await()
    }
}

您需要一些东西来将异步代码转换回同步代码。为此,您需要某种线程池来执行。这里我们使用 Rx 的线程池,但如果你想使用其他池,也可以。

关于android - 如何在 Kotlin 中将 Fuel 与协程一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52145644/

相关文章:

android - finally block 错误 "Variable reader must be initialised"

android - CoroutineScope的范围是什么?

kotlin - 如何从外部非挂起函数构建序列

unit-testing - Kotlin 协程单元测试失败,错误为 "Module with the Main dispatcher had failed to initialize"

java - android 计费 :4. 0.0 - queryPurchases(INAPP) 和 purchase.getSku()

android - Activity 崩溃时,该过程仍然有效,我无法杀死它

java - AlertDialog.Builder 错误

android - 启用R8导致应用程序崩溃

java - iOS 日历的 Android 对应物是什么?

android - 如何处理多个 NavHosts/NavControllers?