android - 如何等待 2 个并行改造调用都完成?

标签 android kotlin retrofit viewmodel

我想并行调用 2 个改造服务,然后仅在它们都完成时才执行操作,但我似乎不知道如何做。

我有一个 viewModel,我在其中定义了我的服务:

var config= List<Configuration>
fun getClientProducts() {
    getClientClientConfigUseCase
        .build(this)
        .executeWithError({ config ->
             config = config
        }, {
           
        })
}

var therapies = List<DtoTherapy>
fun getTherapies() {
    getTherapiesUseCase
        .build(this)
        .executeWithError({ config ->
             therapies = it
        }, {
            
        })
}

然后我想在我的 fragment 中并行调用这两个服务:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
   
    setupUi(view)
    loadUserData()

    viewModel.getClientProducts()
    viewModel.getTherapies()
}

当变量 config 和 therapies 都具有值时执行操作。但正如我所说,也许一个服务需要 1 秒来响应,而另一个服务需要 4 秒,我只想在两者都完成后执行一个操作。任何帮助将不胜感激。

这是我用来构建用例调用的类:

abstract class SingleUseCase<T> : UseCase() {
    private lateinit var single: Single<T>
    private lateinit var useCaseInterface: UseCaseInterface
    private var withLoader: Boolean = false
    private var withErrorMessage: Boolean = false

    internal abstract fun buildUseCaseSingle(): Single<T>

    fun build(useCaseInterface: UseCaseInterface): SingleUseCase<T> {
        this.withLoader = false
        this.withErrorMessage = false

        this.useCaseInterface = useCaseInterface
        this.single = buildUseCaseSingle()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .doAfterSuccess { useCaseInterface.onSuccess(it) }
        return this
    }

    fun withLoader(): SingleUseCase<T> {
        this.withLoader = true
        return this
    }

    fun withErrorMessage(): SingleUseCase<T> {
        this.withErrorMessage = true
        return this
    }

    fun single(): Single<T> {
        return this.single
    }

    fun execute(onSuccess: ((t: T) -> Unit)) {
        useCaseInterface.onPrepareRequest(withLoader)
        buildObservable(onSuccess)
    }

    private fun buildObservable(onSuccess: ((t: T) -> Unit)) {
        disposeLast()
        lastDisposable = single
            .doFinally { useCaseInterface.onFinishRequest(this.withLoader) }
            .subscribe(
                { onSuccess(it) },
                {
                    useCaseInterface.onError(mapError(it), withErrorMessage)
                })

        lastDisposable?.let {
            compositeDisposable.add(it)
        }
    }

    fun executeWithError(onSuccess: ((success: T) -> Unit), onError: ((error: ApiError ) -> Unit)) {
        useCaseInterface.onPrepareRequest(withLoader)
        buildObservable(onSuccess, onError)
    }

    private fun buildObservable(onSuccess: ((success: T) -> Unit), onError: ((error: ApiError ) -> Unit)) {
        disposeLast()
        lastDisposable = single
            .doFinally { useCaseInterface.onFinishRequest(this.withLoader) }
            .subscribe(
                { onSuccess(it) },
                {
                    onError(mapError(it))
                    useCaseInterface.onError(mapError(it), withErrorMessage)
                })

        lastDisposable?.let {
            compositeDisposable.add(it)
        }
    }

    private fun mapError(t: Throwable): ApiError {
        return if(t is HttpException) {
            val apiError = t.response()?.errorBody()?.string()
            try {
                ApiError (t.code(), t.response()?.errorBody()?.string(), Gson().fromJson(apiError, GenericError::class.java))
            } catch(e: Exception) {
                ApiError (-2, "Unkown error")
            }
        } else ApiError (-1, "Unkown error")
    }
}

这是一个特定的用例类:

class GetClientConfigUseCase @Inject constructor(private val repository: UserRepository) :
    SingleUseCase<ClientConfigResponse>() {

    override fun buildUseCaseSingle(): Single<ClientConfigResponse> {
        return repository.getUserConfig()
    }
}

最佳答案

我猜你需要压缩操作。通过 zip 操作,当两个 observable 都收到数据时,您可以在一个地方得到两个 observable 的结果。

Observable<List<ClientProducts>> observable1 = ...
Observable<List<DtoTherapy>> observable2 = ...

Observable.zip(observable1, observable2, new BiFunction<List<ClientProducts>, List<DtoTherapy>, Result>() {

    @Override
    public Result apply(List<ClientProducts> products, List<DtoTherapy> therapies) throws Exception
    {
        // here you have both of your data
        // do operations on products and therapies
        // then return the result
        return result;
    }
});

关于android - 如何等待 2 个并行改造调用都完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72476825/

相关文章:

android - 在android中以一定角度绘制图像

android - java.lang.RuntimeException : Duplicate class com. google.protobuf.AbstractMessageLite 添加firebase远程配置时

intellij-idea - 无法使用yeoman生成器Gradle + Kotlin生成新项目

java - 改造响应正文为空但状态代码为 200

java - 改造 - 当我调用 Intent 打开新 Activity 时应用程序崩溃

java - 更新后只下载文件?

android - 创建 AVD 时出错。有关详细信息,请参阅 idea.log。 Ubuntu 16.04

android - 无法打开编辑器。 Android XML 编辑器无法处理此输入

java - WifiManager 中的 startScan() 在 Android P 中已弃用

java - 我是否使用改造正确提交了此 POST 正文?