问题描述
我查找了许多文章,并试图了解使用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
})