You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何改造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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 00:22:15