gpt4 book ai didi

android - 有进展的整洁架构用例[无 RxJava]

转载 作者:行者123 更新时间:2023-11-30 04:58:31 25 4
gpt4 key购买 nike

我在尝试找出实现 UseCase 的最佳方法时遇到了问题。我看过这样的例子:

谷歌 I/O 安卓应用 https://github.com/google/iosched/blob/master/shared/src/main/java/com/google/samples/apps/iosched/shared/domain/UseCase.kt

我不喜欢的是:

  • 您可以在 UI 中接收结果并在那里做出很多决定。
  • 没有进展

我认为是对上述内容的升级:

Android 架构蓝图

https://github.com/android/architecture-samples/blob/usecases/app/src/main/java/com/example/android/architecture/blueprints/todoapp/domain/ActivateTasksUseCase.kt

他们正在使用协程,现在结果在 ViewModel 中,而且好多了。但同样:没有进展

我的问题是每个人都在使用 RxJava,因为其他人都在使用它。我看到很多人认为这是“在后台执行任务”的东西。但这对我来说太多了。我不需要它。

我看过一些使用协程 channel 的例子,但它们真的很丑。

最近我偶然发现了 Roman Elizarov 的这篇文章:

https://medium.com/@elizarov/callbacks-and-kotlin-flows-2b53aa2525cf

我做了这样的事情:

class ProduceValueWithProgressUseCase @Inject constructor(
private val executor: Executor
) {

operator fun invoke(): Flow<Result<Int, Int>> {
return callbackFlow {
val callback = object : CallbackProgress {
override fun onProgress(result: Int) {
offer(Result.Loading(result))
}

override fun onSuccess(result: Int) {
offer(Result.Success(result))
close()
}

override fun onError(e: Exception) {
offer(Result.Error(e))
close()
}

}

val producer = ValueWithProgressProducer(callback)
executor.execute(producer)
awaitClose {}
}
}

}

这个想法是“生产者”这个东西像大多数“旧”API 一样使用回调来传播数据。所以我想通过流将代码传播到 ViewModel,而不是将回调放在那里。像这样:

viewModelScope.launch {
produceValueWithProgressUseCase().collect {
when (it) {
is Success -> view.showWithProgressResult(it.data)
is Loading -> view.updateProgress(it.progress)
else -> view.showError()
}
}
}

是的,基本上 Flows API 会为我完成这项工作。我什至创建了一个小应用程序来测试它,我只生成数字,它运行良好。我不喜欢的是:

  • 太多的 ExperimentalCoroutinesApi 注释必须到位。例如这里(抱歉格式化):

    @Suppress("NOTHING_TO_INLINE")@ExperimentalCoroutinesApipublic inline fun callbackFlow(@BuilderInference noinline block :暂停ProducerScope.() -> Unit): Flow = channel 流( block )

以上代码是文件的一部分:kotlinx.coroutines.flow.Builders.kt 来自版本:kotlinx-coroutines-core-1.3.2

  • 有时我用@Preview 注释点击了一些东西。(老实说,我不记得在哪里了。那是我删除的东西。)
  • 我只是尝试了一点,看看测试会如何进行,但这并不简单。您可以在 Blueprinst 的代码中看到相同的内容。
  • 我还将执行任务的代码和任务本身混合在一起。我的意思是 callbackFlow() 的用法。

所以最后我看到了一些看起来像是在为明年的改变而尖叫的东西。因此,请发表您的看法。

最佳答案

因此,我将根据您在问题描述中提出的内容向您展示一个实现,请随时提出更多问题,甚至提出改进建议。

当前的实现基于 Kotlin Coroutines 1.3.2 的稳定版本。

回调接口(interface)

interface CallbackProgress {
suspend fun onProgress(result: Int)
suspend fun onSuccess(result: Int)
suspend fun onError(exception: Exception)
}

制作人迭代并执行一些回调的方法。试图模仿你的。

class Producer(private val callback: CallbackProgress) {
suspend fun execute(fail: Boolean) {
(0 until 10).forEach {
when {
it < 9 -> callback.onProgress(it)
fail -> callback.onError(InterruptedException("blabla"))
else -> callback.onSuccess(it)
}
delay(500)
}
}
}

状态

sealed class State {
class Success(val value: Int) : State()
class Loading(val progress: Int) : State()
class Error(val exception: Exception) : State()
}

互动者您在这里需要小心,因为排放应该在同一个协同程序中完成,否则您将需要使用不稳定的 API,例如 channelFlow .

class UseCase {
operator fun invoke(fail: Boolean) = flow {
val callback = object : CallbackProgress {
override suspend fun onSuccess(result: Int) {
withContext(coroutineContext) { emit(State.Success(result)) }
}

override suspend fun onError(exception: Exception) {
withContext(coroutineContext) { emit(State.Error(exception)) }
}

override suspend fun onProgress(result: Int) {
withContext(coroutineContext) { emit(State.Loading(result)) }
}
}

Producer(callback).execute(fail)
}
}

为了测试以上内容,我编写了以下内容,其中演示了故障排放和非故障排放。

fun main() = runBlocking {
val useCase = UseCase()
useCase(true).collect {
when (it) {
is State.Loading -> println("State for failure [Loading -> ${it.progress}]")
is State.Success -> println("State for failure [Success -> ${it.value}]")
is State.Error -> println("State for failure [Error -> ${it.exception.message}]")
}
}
useCase(false).collect {
when (it) {
is State.Loading -> println("State without failure [Loading -> ${it.progress}]")
is State.Success -> println("State without failure [Success -> ${it.value}]")
is State.Error -> println("State without failure [Error -> ${it.exception.message}]")
}
}
}

输出

State for failure [Loading -> 1]
State for failure [Loading -> 2]
State for failure [Loading -> 3]
State for failure [Loading -> 4]
State for failure [Loading -> 5]
State for failure [Loading -> 6]
State for failure [Loading -> 7]
State for failure [Loading -> 8]
State for failure [Error -> blabla]

-------------------------------------

State without failure [Loading -> 0]
State without failure [Loading -> 1]
State without failure [Loading -> 2]
State without failure [Loading -> 3]
State without failure [Loading -> 4]
State without failure [Loading -> 5]
State without failure [Loading -> 6]
State without failure [Loading -> 7]
State without failure [Loading -> 8]
State without failure [Success -> 9]

关于android - 有进展的整洁架构用例[无 RxJava],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58714389/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com