Dnv*_*raj 3 android mvvm viewmodel observer-pattern android-livedata
我查找了很多文章,试图了解使用 MVVM 架构时 Live Data 是如何观察变化的。
我有一个 Fragment A、ViewModel 和 Repository 类。onCreateView()ViewModel 在片段的方法中启动。onCreateView()在fragment方法中紧接着启动API调用。来自服务器的数据是通过片段的方法观察的。onViewCreated
首先,它运行得非常好。但是当我从另一个片段 B 更新用户名并返回片段 A 时。
Fragment A 的方法中再次调用 ApionResume()来更新 UI。但这里我的实时数据不再被观察到,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
}
}
Run Code Online (Sandbox Code Playgroud)
我认为你的问题是每次使用你的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)
}
}
Run Code Online (Sandbox Code Playgroud)
而这对于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 -> {
}
}
}
}
})
}
Run Code Online (Sandbox Code Playgroud)
对于观察者,像以前一样使用 LiveData:
dealerHomeViewModel.dealerInfoLiveData.observe(viewLifecycleOwner, androidx.lifecycle.Observer {dealerInfo ->
// Update UI
tvDealerName.text = dealerInfo.name
})
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3249 次 |
| 最近记录: |