0

我刚刚开始实现MVVM 架构

我有一个这样的存储库:

object ConfigsSSOT {

    val liveData: MutableLiveData<DataWrapper<ConfigsResponse>> = MutableLiveData<DataWrapper<ConfigsResponse>>()

    fun initConfigs() {
        liveData.value = DataWrapper.loading()

        RetrofitBuilder.createConfigs().mainConfigs(
            BuildConfig.VERSION_CODE,
            SettingsSSOT.getTimestamp(),
            TranslationsSSOT.getTimestamp(),
            CitySSOT.getTimestamp()
        ).enqueue(ApiCallback(liveData))
    }

}

在视图模型中我有这个:

    private val _configsLiveData: MutableLiveData<DataWrapper<ConfigsResponse>> = SSOT.configsSSOT.liveData
    private val _shouldUpdateLiveData: LiveData<Boolean> = Transformations.map(_configsLiveData, ::_mapShouldUpdate)

    private fun _mapShouldUpdate(configs: DataWrapper<ConfigsResponse>): Boolean {
        return (configs.status != TStatus.LOADING && configs.data?.shouldUpdate ?: false)
    }

    fun initConfigs() {// !!!!!!!! This is what I call from the Fragment to make the API call
        ConfigsSSOT.initConfigs()
    }

我的问题是,暴露的 liveDataConfigsSSOT可能会在另一个中使用Fragment,另一个可以调用 initConfigs() (假设使用其他值)但是因为 Repository 是一个单例,它会返回相同的 liveData 对象。我不想要那个。

一个解决方案是在每次调用时创建一个新的 liveData 对象,即

 object ConfigsSSOT {
    
    fun initConfigs() : MutableLiveData<DataWrapper<ConfigsResponse>>{
        var liveData: MutableLiveData<DataWrapper<ConfigsResponse>> = MutableLiveData<DataWrapper<ConfigsResponse>>()
        liveData.value = DataWrapper.loading()
    
        RetrofitBuilder.createConfigs().mainConfigs(
                BuildConfig.VERSION_CODE,
                SettingsSSOT.getTimestamp(),
                TranslationsSSOT.getTimestamp(),
                CitySSOT.getTimestamp()
        ).enqueue(ApiCallback(liveData))
    
        return liveData
    }
    
}

但是现在出现了2个问题

1.我需要重做这一行_shouldUpdateLiveData = Transformations.map(_configsLiveData, ::_mapShouldUpdate),因为 viewModel 中的 _configsLiveData 已更改

即是这样的:

    fun initConfigs() : MutableLiveData<DataWrapper<ConfigsResponse>> {
        liveData = ConfigsSSOT.initConfigs()
        _shouldUpdateLiveData = Transformations.map(_configsLiveData, ::_mapShouldUpdate)
        return liveData
    }

这似乎是一个非常糟糕的做法,而且......如果我的布局(xml)检索并观察了 liveData 但是我用另一个实例替换了那个 liveData 实例,xml 将观察到永远不会被再次调用的东西

2.那不是意味着 LiveData 对象会被泄露吗?如果我为每次调用生成新的,假设用户按下一个按钮,我每次都进行 API 调用并每次生成一个新的 LiveData 对象,那么旧的会发生什么?!

需要帮助: 我找不到该场景的任何解决方案和最佳实践:使用相同的存储库进行 API 调用,使用存储库中的 liveData 将数据发送回“viewModel 调用者”,但不要为每个调用实例化 liveData ,而是以某种方式使用相同的,但是当从不同的视图模型进行调用时,不要使用相同的 liveData 调用。

所以,所以,令人困惑!

编辑

由于评论部分中的一些讨论,添加了 RetrofitBuilder

object RetrofitBuilder {

    private val _okHttpClient = OkHttpClient().newBuilder()
        .connectTimeout(60, TimeUnit.SECONDS)
        .readTimeout(60, TimeUnit.SECONDS)
        .writeTimeout(60, TimeUnit.SECONDS)
        .cache(null)
        .build()

    private val _retrofitBuilderMill = Retrofit.Builder()
        .baseUrl(BuildConfig.URL_BASE + "/api/")
        .addConverterFactory(GsonConverterFactory.create())
        .client(_okHttpClient)
        .build()

    private val _retrofitBuilderPizza = Retrofit.Builder()
        .baseUrl("https://www.validator.pizza")
        .addConverterFactory(GsonConverterFactory.create())
        .client(_okHttpClient)
        .build()

    fun <S> createGenericService(serviceClass: Class<S>?): S {
        return _retrofitBuilderMill.create(serviceClass)
    }

    fun createPizza(): PizzaApiService {
        return _retrofitBuilderPizza.create(PizzaApiService::class.java)
    }

    fun createConfigs(): ConfigsApiService {
        return createGenericService(ConfigsApiService::class.java)
    }

    fun createAuth(): AuthApiService {
        return createGenericService(AuthApiService::class.java)
    }

}
4

0 回答 0