在 Android 中,在一个 api 调用中列出 api 调用

In Android, Make a list of api call inside one api call

在我的一个 android 应用程序中,起初我想调用一个 api,它将 return 一个项目列表,并且该项目将显示在 RecyclerView 中.我还需要为 RecyclerView 的每个项目调用另一个 api 以获取该项目的描述并根据它们的 id 显示对每个项目的描述。我该如何解决这种情况。

Subject.kt

data class Subject(
    val subject: String,
    val subjectCode:String,
    val subjectIcon: String,
    val progress: Double = 0.0,
)

SubjectRepository.kt

interface SubjectRepository {
    fun getAllSubject(): Observable<List<Subject>>
    fun getProgressAnalysisOf(subjectCode: String): Observable<Double>
}

SubjectViewModel.kt

class HomeViewModel @Inject constructor(
    private val subjectRepository: SubjectRepository,
) : BaseViewModel() {

    val subjectList = MutableLiveData<List<Subject>>()
    val progress = MutableLiveData<Double>

    fun getAllSubject() {
        compositeDisposable += subjectRepository.getAllSubject()
            .performOnBackgroundOutputOnMain()
            .doOnSubscribe { loader.value = true }
            .doAfterTerminate { loader.value = false }
            .subscribe({
                subjectList.value = it
            }, {
                handleException(it)
            })
    }

    fun getProgressAnalysisOf(subjectCode: String) {
        compositeDisposable += subjectRepository. getProgressAnalysisOf(subjectCode)
            .performOnBackgroundOutputOnMain()
            .doOnSubscribe { loader.value = true }
            .doAfterTerminate { loader.value = false }
            .subscribe({
                progress.value = it
            }, {
                handleException(it)
            })
    }
}

首先,我需要调用 getAllSubject(),它将 return 一个主题列表,然后我在 RecyclerView 中显示该列表。对于回收站视图的每个主题,我必须调用 getProgressAnalysisOf(subjectCode) 并更新该回收站视图的项目。

终于找到解决办法了。我使用 ConnectableObservable 来解决这个问题。

  1. 您可以注意到使用了 replay() 运算符 (getAllSubject().replay()) 使 Observable 发出新订阅的数据而无需 再次重新执行逻辑。
  2. 在我的例子中,主题列表将在不进行 再次调用 HTTP。如果没有 replay 方法,您会注意到 getAllSubject() HTTP 调用被执行多次。
  3. 第一次订阅时,直接添加主题列表 Adapter class 和 RecyclerView 直接渲染而不用 主题的进度值。
  4. 在第二次订阅中,flatMap()用于转换列表 受个别主题发射的影响。
  5. 在同一个Observable上,链接了另一个flatMap来执行 每个主题发射的 getProgressAnalysisOf() 方法 获取进度值。
  6. 收到进度信息后,特定的行项目 在 RecyclerView 中更新。

HomeViewModel.kt

class HomeViewModel @Inject constructor(
    private val subjectRepository: SubjectRepository,
) : BaseViewModel() {

    val subjectList = MutableLiveData<List<Subject>>()
    val progress = MutableLiveData<Double>
    var subjectsObservable: ConnectableObservable<List<Subject>> = subjectRepository.getAllSubject().replay()

    fun getAllSubject() {
        compositeDisposable += subjectsObservable
        .performOnBackgroundOutputOnMain()
        .doOnSubscribe { loader.value = true }
        .doAfterTerminate { loader.value = false }
        .subscribe({
            subjectList.value = it
        }, {
            handleException(it)
        })
    }

    fun getProgressAnalysisOf() {
        compositeDisposable += subjectsObservable
        .performOnBackgroundOutputOnMain()
        .flatMap { Observable.fromIterable(it) }
        .flatMap { subjectRepository.getProgressAnalysisOf(it.code) }
        .subscribe({
            analysisData.postValue(it)
        }, {
            handleException(it)
        })
}

HomeActivity.kt

class HomeFragment : BaseFragment<HomeViewModel>() {

    private val subjectAdapter: SubjectAdapter by lazy {
        SubjectAdapter {

        }
    }

    override fun onResume() {
        super.onResume()

        viewModel.getAllSubject()
        viewModel.getPerformanceAnalysisOf()
        viewModel.subjectsObservable.connect()
    }

    override fun observeLiveData() {
        observe(viewModel.subjectList) {
            subjectAdapter.submitList(it)
        }

        observe(viewModel.analysisData) {
            // update the analysis value for each item
        }
    }
}