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

Kotlin多平台集成Apollo GraphQL实现可观察模式方案咨询

Reaktive 对接带加载态链式调用实现方案

整个实现不需要改动原有Apollo GraphQL的核心请求逻辑,只需要做三层通用封装,所有代码可直接放在KMP共享模块,双端复用:

  • 第一步:定义通用请求状态密封类
    覆盖加载中、请求成功、请求失败三种状态,作为整个链式调用的流传递类型:
    sealed class RequestState<out T> {
        data object Loading : RequestState<Nothing>()
        data class Success<T>(val data: T) : RequestState<T>()
        data class Error(val throwable: Throwable) : RequestState<T>()
    }
    
  • 第二步:实现挂起函数到Reaktive Observable的通用转换
    引入Reaktive协程互操作模块后,写一个通用扩展方法,任意挂起函数都可以转成发射三种状态的可观察流,订阅时第一时间发射加载态,再执行实际请求逻辑,自动捕获异常:
    import com.badoo.reaktive.coroutinesinterop.singleFromCoroutine
    import com.badoo.reaktive.observable.Observable
    import com.badoo.reaktive.observable.observable
    import com.badoo.reaktive.observable.subscribeScoped
    
    fun <T> (suspend () -> T).asStateObservable(): Observable<RequestState<T>> {
        return observable { emitter ->
            emitter.onNext(RequestState.Loading)
            singleFromCoroutine { invoke() }
                .subscribeScoped(
                    onSuccess = {
                        emitter.onNext(RequestState.Success(it))
                        emitter.onComplete()
                    },
                    onError = {
                        emitter.onNext(RequestState.Error(it))
                        emitter.onComplete()
                    }
                )
        }
    }
    
  • 第三步:改造Repository层方法
    把原有挂起函数的逻辑包在suspend闭包中,返回包装后的状态流。注意原有逻辑中请求失败的分支不要直接返回错误模型,改为抛出对应业务异常,即可被错误回调捕获:
    fun addFeedback(request: AddFeedBackRequest): Observable<RequestState<BaseResponseModel<Any>>> {
        val requestBlock: suspend () -> BaseResponseModel<Any> = {
            val feedBackType = if (request.type == AddFeedBackType.Bug) {
                FeedbackType.BUG
            } else {
                FeedbackType.FEEDBACK
            }
            val input = AddFeedbackInput(request.note, Optional.presentIfNotNull(feedBackType))
            val mutation = AddFeedbackMutation(input)
            val response = executeMutation(mutation)
            if (response.isFailed()) throw BizException(response.errorMsg)
            onSuccess()
        }
        return requestBlock.asStateObservable()
    }
    
  • 第四步:实现三个链式回调扩展
    写三个通用扩展方法,自动识别流里的状态类型,分发到对应回调,不需要每次订阅都做类型判断:
    import com.badoo.reaktive.observable.Observable
    import com.badoo.reaktive.observable.doOnBeforeNext
    
    inline fun <T> Observable<RequestState<T>>.onLoading(crossinline block: () -> Unit): Observable<RequestState<T>> {
        return doOnBeforeNext { if (it is RequestState.Loading) block() }
    }
    
    inline fun <T> Observable<RequestState<T>>.onSuccess(crossinline block: (T) -> Unit): Observable<RequestState<T>> {
        return doOnBeforeNext { if (it is RequestState.Success) block(it.data) }
    }
    
    inline fun <T> Observable<RequestState<T>>.onError(crossinline block: (Throwable) -> Unit): Observable<RequestState<T>> {
        return doOnBeforeNext { if (it is RequestState.Error) block(it.throwable) }
    }
    

调用方式

安卓端使用时直接绑定生命周期作用域,页面销毁时自动取消订阅,完全匹配预期的链式写法:

HelpRepository()
    .addFeedback(AddFeedBackRequest(AddFeedBackType.Bug, ""))
    // 按需指定线程,io线程执行请求,主线程回调
    // .subscribeOn(ioScheduler)
    // .observeOn(mainScheduler)
    .onLoading {
        // 展示加载进度条
    }
    .onSuccess { response ->
        // 处理成功逻辑
    }
    .onError { err ->
        // 展示错误提示
    }
    .subscribe(lifecycleScope.asDisposableScope())

补充说明

  • 整套封装属于通用逻辑,所有KMP层的接口都可以复用这套转换,不需要每个接口单独写状态处理
  • iOS端可以直接把Reaktive的Observable转成RxSwift的Observable,复用同一套状态定义,不需要双端重复写加载态逻辑
  • 原有Apollo的请求逻辑、异常处理逻辑不需要做本质修改,仅需要把原来返回错误模型的分支改为抛出异常即可

内容的提问来源于stack exchange,提问作者ALKIN ÇAKIRALAR

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 18:39:34