Kotlin Flow - 带结果密封类的 Retrofit 通用函数

Teo*_*Teo 4 retrofit kotlin-flow

我最近正在改造Flow我的存储库。

结果密封类

enum class ApiStatus{
    SUCCESS,
    ERROR,
    LOADING
}

sealed class ApiResult <out T> (val status: ApiStatus, val data: T?, val message:String?) {

    data class Success<out R>(val _data: R?): ApiResult<R>(
        status = ApiStatus.SUCCESS,
        data = _data,
        message = null
    )

    data class Error(val exception: String): ApiResult<Nothing>(
        status = ApiStatus.ERROR,
        data = null,
        message = exception
    )

    data class Loading<out R>(val _data: R?, val isLoading: Boolean): ApiResult<R>(
        status = ApiStatus.LOADING,
        data = _data,
        message = null
    )
}
Run Code Online (Sandbox Code Playgroud)

3 种状态的存储库调用示例 - 正在加载、错误、成功

    fun googleDisconnect() = flow {
        emit(ApiResult.Loading(null, true))  

        val call = userDataSource.self("v4").googleDisconnect()

        if(call.isSuccessful) {
            emit(ApiResult.Success(call.body()))
        } else {
            emit(ApiResult.Error("Google Disconnect Failed"))
        }
    }
Run Code Online (Sandbox Code Playgroud)

但是,我的存储库中有多个具有不同功能的网络调用。是否有任何想法为这些编写一个通用函数,flow以便这些流可以发送到流构建器?

我的尝试但问题是如何将挂起函数传递到函数中? 在此输入图像描述

在此输入图像描述

Teo*_*Teo 6

最后我给自己找到了答案。我想知道这是否有帮助,但我会发布我的答案。

fun <T> toResultFlow(call: suspend () -> Response<T>?) : Flow<ApiResult<T>?> {
    return flow {
        emit(ApiResult.Loading())

        val c = call()  <-- have to initialize the call method first
        c?.let {
            try{
                if(c.isSuccessful) {
                    c.body()?.let {
                        emit(ApiResult.Success(it))
                    }
                } else {
                    c.errorBody()?.let {
                        val error = it.string()
                        it.close()
                        emit(ApiResult.Error(error))
                    }
                }
            }catch (e: Exception) {
                emit(ApiResult.Error(e.toString()))
            }
        }

    }.flowOn(Dispatchers.IO)
}

Run Code Online (Sandbox Code Playgroud)

然后,将挂起函数作为 lambda 传递

fun googleDisconnect() = toResultFlow {
    userDataSource.self("v4").googleDisconnect()
}  
Run Code Online (Sandbox Code Playgroud)

最后,toResultFlow将返回 Flow<ApiResult> 并且T是您首选的数据类型!沃拉!