Live Data Observer仅调用一次再次调用api更新UI时,它不是从服务器更新数据

问题描述

我查找了许多文章,并试图了解使用MVVM体系结构时如何观察实时数据的变化。

我有一个Fragment A,viewmodel和Repository类。 viewmodel在片段的onCreateView()方法中启动。 之后,在片段的onCreateView()方法中启动Api调用。 在片段的onViewCreated方法观察到来自服务器的数据。

首先,它运行得很好。但是,当我从另一个片段B更新用户名并返回到片段A时。

在片段A的onResume()方法中再次调用

Api以更新UI。 但是这里不再显示我的实时数据,用户界面也没有更新

我不明白自己在做什么错?为什么观察者没有第二次触发?

下面是代码

class FragmentA : Fragment(){

    private lateinit var dealerHomeviewmodel: DealerHomeviewmodel
  
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

    override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.fragment_home_dealers,container,false)

        val dealerHomeFactory = DealerHomeFactory(token!!)
        dealerHomeviewmodel = viewmodelProvider(this,dealerHomeFactory).get(DealerHomeviewmodel::class.java)

      dealerHomeviewmodel.getDealerHomeData()
        return view
    }

 override fun onViewCreated(view: View,savedInstanceState: Bundle?) {
        super.onViewCreated(view,savedInstanceState)
          dealerHomeviewmodel.dealerInfoLiveData.observe(viewLifecycleOwner,androidx.lifecycle.Observer {dealerInfo ->
            // Update UI
            tvDealerName.text = dealerInfo.name
        
        })
    }

 override fun onResume() {
        super.onResume()
        dealerHomeviewmodel.getDealerHomeData()
    }
}

//=========================== VIEW MODEL ===================================//
class DealerHomeviewmodel(val token:String) : viewmodel() {

    var dealerInfoLiveData:LiveData<DealerInfo>

    init {
        dealerInfoLiveData = mutablelivedata()
    }

    fun getDealerHomeData(){
        dealerInfoLiveData = DealerHomeRepo().getDealerHomePageInfo(token)
    }
}

//======================== REPOSITORY ================================//
class DealerHomeRepo {

    fun getDealerHomePageInfo(token:String):LiveData<DealerInfo>{
        val responseLiveData:mutablelivedata<DealerInfo> = mutablelivedata()
        val apiCall: ApiCall? = RetrofitInstance.getRetrofit()?.create(ApiCall::class.java)
        val dealerInfo: Call<DealerInfo>? = apiCall?.getDealerInfo(Constants.BEARER+" "+token,Constants.XML_HTTP)

        dealerInfo?.enqueue(object : Callback<DealerInfo>{
            override fun onFailure(call: Call<DealerInfo>,t: Throwable) {
                Log.d(Constants.TAG,t.toString())
            }

            override fun onResponse(call: Call<DealerInfo>,response: Response<DealerInfo>) {
                if(response.isSuccessful){
                    when(response.body()?.status){
                        Constants.SUCCESS -> {
                            responseLiveData.value = response.body()
                        }

                        Constants.FAIL -> {

                        }
                    }
                }
            }
        })

        return responseLiveData
    }
}

解决方法

我认为您的问题是,每次使用getDealerHomePageInfo(token:String方法时,您都会生成一个新的mutableLiveData。

第一次调用getDealerHomePageInfo(token:String)时会生成一个MutableLiveData,然后在onViewCreated上观察到,它就有一个值。

onResume中,您再次调用getDealerHomePageInfo(token:String)来生成一个新的MutableLiveData,以便您的观察者指向旧的。

解决问题的方法是将viewModel的引用传递到存储库,以便它使用每个新值更新MutableLiveData,而不是每次都生成一个新值。

编辑答案:

我会为ViewModel做这样的事情:

class DealerHomeViewModel(val token:String) : ViewModel() {
    private val _dealerInfoLiveData:MutableLiveData<DealerInfo> = MutableLiveData()
    val dealerInfoLiveData:LiveData = _dealerInfoLiveData


    fun getDealerHomeData(){
        DealerHomeRepo().getDealerHomePageInfo(token,_dealerInfoLiveData)
    }
}

这是DealerHomeRemo

class DealerHomeRepo{

    fun getDealerHomePageInfo(token:String,liveData: MutableLiveData<DealerInfo>){
        val apiCall: ApiCall? = RetrofitInstance.getRetrofit()?.create(ApiCall::class.java)
        val dealerInfo: Call<DealerInfo>? = apiCall?.getDealerInfo(Constants.BEARER+" "+token,Constants.XML_HTTP)

        dealerInfo?.enqueue(object : Callback<DealerInfo>{
            override fun onFailure(call: Call<DealerInfo>,t: Throwable) {
                Log.d(Constants.TAG,t.toString())
            }

            override fun onResponse(call: Call<DealerInfo>,response: Response<DealerInfo>) {
                if(response.isSuccessful){
                    when(response.body()?.status){
                        Constants.SUCCESS -> {
                            liveData.value = response.body()
                        }

                        Constants.FAIL -> {

                        }
                    }
                }
            }
        })
    }

对于观察者,请像以前一样使用LiveData:

dealerHomeViewModel.dealerInfoLiveData.observe(viewLifecycleOwner,androidx.lifecycle.Observer {dealerInfo ->
            // Update UI
            tvDealerName.text = dealerInfo.name
        
        })

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...