android - 如何在 Kotlin 中使用 Fuel 和协程?
问题描述
我想获取 API 请求并将请求的数据保存到数据库。还想返回数据(即写入 DB)。我知道,这在 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())
}
}
解决方案
让我们一层一层的看。
首先,据我所知,您的RegionResponse
和Region
完全适合这个用例,所以我们根本不会碰它们。
您的网络层是用 Java 编写的,因此我们假设它总是期望同步行为,并且也不会触及它。
所以,我们从 repo 开始:
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 的线程池,但是如果你想使用其他池,那么就这样做。
推荐阅读
- php - 从 PHP 数组创建 HTML 表
- javascript - 如何动画显示按钮?
- python - 使用多索引列写入和读取 pandas 数据帧
- reactjs - 如何使用 react-router 在单页应用程序中单击按钮滚动到特定的 div?
- java - 有没有办法在初始化枚举时传递变量而不是在java中传递实际值?
- c++ - 有什么方法可以在 GNU Make 中使用变量作为规则和先决条件?
- angular - Angular:mat-select的2路绑定不起作用,在代码中分配值会导致它在UI中重置
- ios - 我们如何快速从 Gmail 链接进入 App 内部
- inno-setup - Inno Setup - 卸载时不显示进度条
- python - 如何提取 super().__init__ 来自的类?