【问题标题】:Android MVVM multiple API CallAndroid MVVM 多 API 调用
【发布时间】:2020-04-25 18:50:45
【问题描述】:

我正在制作一个没有注入依赖库和 RX 复杂性的 MVVM 示例项目(因为我认为对于没有所有这些非常高效的东西的人来说,最好了解它是如何从根本上工作的)但它更难制作:)

我遇到了麻烦,我在这里使用 CatApi:https://thecatapi.com/ 我正在尝试做一个微调器,其中包含品种名称以及左侧的猫图片(对于每个品种),但在此 API 中,您只能通过两次调用获得此结果(一个用于品种,一个用于图像)品种),我不会将 API 的研究推得太远,因为即使 API 可以解决我的问题,我也想面对这个问题,因为它可能在我以后的生活中发生:)

所以我的问题是我做了以下代码:

BreedEntity

package com.example.mvvm_kitty.data.local.entities

//Entity was used to be stored into a local DB so no use here
data class BreedEntity (

    val adaptability: Int,

    val affection_level: Int,

    val description: String,

    val id: String,

    var name: String,

    val life_span: String,

    val origin: String,

    var iconImage : BreedImageEntity?,

    var images: List<BreedImageEntity>?

){

}

调用BreedActivity

  private fun subscribeToModel(breedsViewModel: BreedsViewModel) {

        //Todo: Gerer les erreurs reseau

        breedsViewModel.getBreeds().observe(this, Observer {

            breedEntities ->

            mBinding.catSelected = breedEntities[0]

            breedSpinnerAdapter = BreedsSpinnerAdapter(this, breedEntities)
            mBinding.breedSelector.adapter = breedSpinnerAdapter

            breedEntities.forEach {breedEntity ->
                breedsViewModel.getBreedImages(breedEntities.indexOf(breedEntity)).observe(this, Observer {
                    breedEntity.iconImage = it[0]
                })
            }


        })

    }

是的,我认为 foreach 很脏(而且它不起作用,因为不要同时运行,所以当我在观察者中设置图像时,“it”值在最后一项上

这是我的BreedsViewModel

package com.example.mvvm_kitty.viewmodels

import android.app.Application
import android.util.Log
import android.view.animation.Transformation
import androidx.lifecycle.*
import com.example.mvvm_kitty.BasicApp
import com.example.mvvm_kitty.data.local.entities.BreedEntity
import com.example.mvvm_kitty.data.local.entities.BreedImageEntity
import com.example.mvvm_kitty.data.repositories.CatRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch

class BreedsViewModel(application: Application, private val catRepository: CatRepository) : AndroidViewModel(application) {

    private val mObservableBreeds: LiveData<List<BreedEntity>> = catRepository.getBreeds()

    /**
     * Expose the product to allow the UI to observe it
     */
    fun getBreeds(): LiveData<List<BreedEntity>> {
        return mObservableBreeds
    }

    fun getBreedImages(index : Int): LiveData<List<BreedImageEntity>> {
        val breed = mObservableBreeds.value?.get(index)
        return catRepository.getBreedImages(breed!!.id)
    }

    /**
      * Factory is used to inject dynamically all dependency to the viewModel like reposiroty, or id
     * or whatever
     */
    class Factory(private val mApplication: Application) :
        ViewModelProvider.NewInstanceFactory() {

        private val mRepository: CatRepository = (mApplication as BasicApp).getCatRepository()

        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            return BreedsViewModel(mApplication, mRepository) as T
        }
    }

}

并完成 CatRepository 方法以获取图像:


    private fun getBreedImagesFromApi(id: String) : LiveData<List<BreedImageEntity>>{

            mObservableBreedImages.addSource(catService.getAllImages(id, 10)){

                mObservableBreedImages.postValue(it.resource?.map { breedDto ->
                    breedDto.toEntity()})

            }


        return mObservableBreedImages
    }

我的问题是如何以干净的方式获取每个项目的图像(因为我认为我的代码很好但 foreach 观察者部分很脏)

如果有人可以帮助我,那就太好了:D,提前感谢您的时间。

【问题讨论】:

  • 几乎可以肯定 switchMap 转换会有所帮助。不过,我现在没有时间写一个例子。在这里查看developer.android.com/reference/android/arch/lifecycle/… 应该类似于 Transformations.switchMap(catRepository.getBreeds) { // 这里调用方法来获取每个品种的图像并使用图像创建 Breeds 实体 }
  • 不要使用嵌套的观察者,使用Transformations.switchMap

标签: android kotlin mvvm android-architecture-components


【解决方案1】:

似乎不是单独获取数据,您应该同时获取它们并将结果组合成一个响应。

一般来说:

  1. 删除getBreedImagesFromApi
  2. 更新您的getBreedsFromApi(我 假设存在并且您正在使用协程)来获取这两个部分 您已经拥有的用于获取品种的一次调用中的数据。你可以 使用async and await() 来触发对两个不同端点的两个请求,让它们同时运行,然后等待两个请求完成。
  3. 删除“foreach”,因为在您获得品种列表时图像现在已经存在。

希望有帮助!

【讨论】:

  • 好的,这就是我认为首先要使用的,所以我将尝试使用协程 :) 我会与您联系谢谢
【解决方案2】:

我猜视图应该从您的视图模型中接收到完整的对象数据, 这意味着您必须在视图 model.so 中执行所有这些逻辑

  1. 点击这两个 API 并在视图模型中观察它们。
  2. 再创建一个负责将数据传递到您的视图(活动/片段)的实时数据
  3. 从两个 API 观察者更新 ViewLiveData。

为此,您需要在视图模型中使用 TransformationMediatorLiveData

你也可以使用 Rxjava,查看fetch every item on the list

【讨论】:

    猜你喜欢
    • 2019-10-05
    • 2021-12-15
    • 2022-12-09
    • 2023-01-21
    • 1970-01-01
    • 2023-04-03
    • 2021-02-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多