【问题标题】:Where to make API's requests while using MVVM architecture in android? [closed]在 android 中使用 MVVM 架构时在哪里发出 API 请求? [关闭]
【发布时间】:2020-06-26 07:49:56
【问题描述】:

我在我的应用程序中使用 MVVM 架构,我想从活动的视图模型类发出 API 请求。这里的问题是我没有得到最好的方法。由于 viewmodel 已经知道该活动的生命周期,因此不需要为 API 创建单独的 viewmodel 类吗?如果是这样,那么我应该从 viewmodel 类触发正常的改造请求,还是在这种情况下最好的方法是什么?

我之前在没有 MVVM 的情况下所做的是:

class UserViewModel : ViewModel() {

    private val cd = CompositeDisposable()
    val status: MutableLiveData<Boolean>? = MutableLiveData<Boolean>()


    val responseImages = MutableLiveData<ResponseImages>()
    fun getImages(text: String) {
        cd.add(
            RetrofitHelper.apiInstance.getImages(Site.METHOD, Site.KEY, text)
                .myApiSubscriber(status)
                .subscribe({
                    responseImages.postValue(it)
                }, {
                    it.printStackTrace()
                })
        )
    }


    private fun <T> Single<T>.myApiSubscriber(status: MutableLiveData<Boolean>?): Single<T> {
        return this.doOnSubscribe {
            status?.postValue(true)
//            Utils.debugger("PROGRESS ", " doOnSubscribe")
        }.doFinally {
            status?.postValue(false)
//            Utils.debugger("PROGRESS ", " doFinally")
        }.subscribeOn(Schedulers.io())
    }

    override fun onCleared() {
        cd.dispose()
        super.onCleared()
    }

    fun callCleared() {
        onCleared()
    }
}

那么上述方法在 MVVM 的情况下是否仍然有用,以及 MVVM 遵循的最佳方法是什么? 请提出建议。

【问题讨论】:

  • 你可以用不同的方式来做。我发现以下文章对 2021 MVVM 非常清晰和有用 - Retrofit 支持“暂停功能”,现在调用非常简单(不需要 .myApiSubscriber(status).subscribe 等)。在 ViewModel 中使用 LiveData 并在存储库中暂停 fun(或 Flow):proandroiddev.com/…

标签: android mvvm android-lifecycle rx-android android-mvvm


【解决方案1】:

首先,我强烈建议您阅读鲍勃叔叔的 SOLID 原则,以了解为什么您还没有分离代码。

遵循的一种常见做法是使用 Android 文档中建议的存储库模式。这是架构的参考: Android Architecture Components Reference

我已经分解了每个块的作用如下:

Activity/Fragment :在这里您可以执行所有与视图相关的操作,例如初始化 RecyclerView、显示对话框、片段事务、显示 toast 等。在这里,您还将为 MutableLiveData 注册观察者(存在于您的 ViewModel 中)

ViewModel:ViewModel 包含归属于 View 的所有业务逻辑。 ViewModel 不负责初始化 API 调用。原因是,可能会发生这样的情况,您需要进一步处理响应并将其存储到数据库中,甚至在 API 出现错误的情况下从数据库中获取数据。

但是,您可以做的是,使用包含执行 API 的所有详细信息的存储库实例调用 API。获取响应后,将值分配给视图模型中的 livedata,由 Fragment/Activity 中注册的观察者观察。

存储库:这通常是执行所有网络操作和数据库操作的地方。这允许将所有数据从 ViewModel 中分离出来。

这是一个简短的例子

class UserViewModel(private val imageRepository) : ViewModel() {

    //Not required since you're using a Single which uses a SingleObserver that  doesn't require to be disposed manually.
    private val cd = CompositeDisposable() 

    val responseImages = MutableLiveData<ResponseImages>()
    val showError = MutableLiveData<Boolean>()

    fun getImages(text: String) =
        imageRepository.getImages(text)
                .observerOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe({
                    responseImages.value = (it)
                }, {
                    showError.value = true
                })


    override fun onCleared() {
        cd.dispose()
        super.onCleared()
    }

    fun callCleared() {
        onCleared()
    }
}

//Note: you should ideally just pass the API instance. unless required. 
class ImageRepository(val retrofitHelper: RetrofitHelper){

    fun getImages(text:String): Single<ResponseImages> {
        return retrofitHelper.apiInstance.getImages(Site.Method,Site.key,text)
    }

}

//In your Activities onCreate()

class HomeActivity: AppCompatActivity(){

    override fun onCreate(bundle: SavedInstanceState?){
        viewModel.responseImages.observer(this,Observer {
            //do something with your ResponseImages
        }
    }
}

还有其他事情可以做,例如,为您的存储库使用策略模式,其中 ImageRepository 是一个接口,ImageRepositoryImpl 具有所有详细信息等。但那是另一次了!

Google 的 SunflowerApp 是一个很好的参考 :)

【讨论】:

  • 但我认为应该在 ViewModel 类而不是在 Activity 中接收或观察响应,因为这就是使用 MVVM 的目的。将有一个存储库类来执行此操作。
  • @CosmicDev 我上面展示的例子就是这样做的。如果您观察到,响应是在视图模型中获取的,并且在 SingleObserver 的 onNext() 中,我将值(假设不需要进一步的转换)分配给 responseImages LiveData。希望能解决这个问题
  • @CosmicDev 如果您觉得答案对您有所帮助,或解决了您的问题。如果您能接受答案,那就太好了!
【解决方案2】:

您可以在 mvvm 模式的存储库类中调用 Api 请求。您可以通过here 参考。

【讨论】:

    猜你喜欢
    • 2014-06-06
    • 2019-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-28
    • 2020-10-05
    • 1970-01-01
    • 2019-12-21
    相关资源
    最近更新 更多