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
相关产品推荐
相关产品推荐

