如何改造Rx Observable类型的UseCase以返回Flow适配Jetpack Compose?
解决方案
1. 添加必要依赖
先确保项目引入kotlinx-coroutines-rx3库,它提供RxJava与Kotlin Flow的双向转换工具:
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-rx3:1.7.3"
2. 改造抽象UseCase类
将原返回Observable<T>的抽象类改为返回Flow<T>,用Rx转Flow的方法替换原Subscriber逻辑:
import io.reactivex.rxjava3.core.Observable import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.rx3.asFlow abstract class UseCase<in Params, out T> { // 保留原execute方法的Observable返回逻辑,内部调用仓库接口 abstract fun execute(params: Params): Observable<T> // 对外暴露的调用入口,自动完成Observable到Flow的转换 fun invoke(params: Params): Flow<T> { return execute(params).asFlow() } }
asFlow()会自动将Observable的onNext事件转为Flow发射值、onError转为Flow异常、onComplete触发Flow结束,完全适配原Rx事件逻辑。
3. 改造具体UseCase实现类
ForgotPasswordUC无需大幅修改,保持原有仓库调用逻辑即可:
class ForgotPasswordUC(private val repository: AuthRepository) : UseCase<String, String>() { override fun execute(params: String): Observable<String> { // 保留原仓库调用,返回Observable<String> return repository.forgotPassword(params) } }
4. 在Jetpack Compose中使用
推荐使用collectAsStateWithLifecycle(遵循页面生命周期)或LaunchedEffect收集Flow:
方式一:collectAsStateWithLifecycle(推荐)
import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun ForgotPasswordScreen(viewModel: ForgotPasswordViewModel = viewModel()) { // 自动收集Flow并转为Compose状态,初始值设为null val forgotPasswordResult = viewModel.forgotPasswordFlow.collectAsStateWithLifecycle(initialValue = null) forgotPasswordResult.value?.let { result -> // 处理成功返回的结果 } }
方式二:LaunchedEffect手动收集
import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun ForgotPasswordScreen(viewModel: ForgotPasswordViewModel = viewModel()) { LaunchedEffect(Unit) { try { viewModel.forgotPasswordUC.invoke("user@example.com").collect { result -> // 处理返回结果 } } catch (e: Exception) { // 捕获并处理异常 } } }
额外优化:全局异常处理
如果需要统一处理Flow异常,可在UseCase的invoke方法中添加catch操作符:
fun invoke(params: Params): Flow<T> { return execute(params) .asFlow() .catch { e -> // 全局异常处理,比如打印日志、发送错误事件 emit(defaultValueWhenError()) // 可选:发送默认值避免页面崩溃 } }
内容的提问来源于stack exchange,提问作者coder_baba
相关产品推荐
相关产品推荐

