我在用项目设置MVVM时遇到了麻烦,除了我注意到LiveData对象的Observers被多次调用之外,一切似乎都运行顺利。有时,同一LiveData对象更新一次4-5次。
主要活动上托管了多个片段,所有片段都链接到连接到我的存储库的同一个ViewModel,然后使用改造向我的服务器发出API请求。
然后,我在每个片段中都有单独的观察者,从ViewModel观察相同的LiveData对象以进行更改,当使用单个片段时,对于相同的更改,我没有多个观察的问题,但是在将项目分支到一个我注意到观察者被称为很多片段。
我已将观察者更改为全部使用viewLifecycleOwner无效。
这是一个片段的示例,每个片段观察LiveData的方式基本上相同,只是它们更新了UI的不同部分。
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProviders.of(this, viewModelFactory)
.get(WeatherViewModel::class.java)
bindUI()
}
private fun bindUI() = launch {
val currentWeatherResponse = viewModel.weatherResponse.await()
currentWeatherResponse.observe(viewLifecycleOwner, Observer {
if(it == null) return@Observer
Log.i("CurrentWeatherFragment", "Observed")
val currentWeather = it.currentWeather.first()
updateTemperature(currentWeather.temperature, currentWeather.tempMin, currentWeather.tempMax)
updateWind(currentWeather.windSpeed, currentWeather.windDirName)
updateHumidity(currentWeather.humidity)
})
}
这是每个片段连接到的ViewModel:
class WeatherViewModel(
private val forecastRepository: IForecastRepository
) : ViewModel() {
val weatherResponse by lazyDeferred {
forecastRepository.getWeatherResponse()
}
}
我的存储库中的天气响应方法:
override suspend fun getWeatherResponse(): LiveData<out DetailedPrediction> {
return withContext(Dispatchers.IO) {
initWeatherData()
println("Get Weather response method")
println(currentWeatherDao.getWeatherResponse().value)
return@withContext currentWeatherDao.getWeatherResponse()
}
}
还有从saveWeatherResponse方法接收数据发布的天气DAO:
private val weatherResponse = MutableLiveData<DetailedPrediction>()
private val radarImages = MutableLiveData<RadarImageList>()
//TODO Return weather response from shared preferences
override fun getWeatherResponse(): LiveData<DetailedPrediction> {
return weatherResponse
}
我希望能够从这个单一的LiveData事件中更新所有UI元素,该事件实际上是有效的,但是观察者触发的次数太多了,我一生都无法找出原因。< / p>
答案 0 :(得分:2)
我不敢相信我花了这么长时间才发现一个简单的错误,但是如果有人遇到这个问题(我对此表示怀疑),我会在每次观察中都添加一个片段,而不是替换该片段,这意味着一个品牌为每个片段创建了新的观察者。
这是旧代码:
drop table if exists table1;
create table table1(id int)
insert into table1 values (2),(3)
drop table if exists #temp;
select * into #temp from(select * from table1 where id=2)a;
drop table if exists #temp;
select * into #temp from(select * from table1 where id=3)a;
和固定代码:
fun addDailyWeatherFragment() {
val fragmentTransaction: FragmentTransaction = fragmentManager!!.beginTransaction()
val dailyWeatherFragment = DailyWeatherFragment()
fragmentTransaction.add(R.id.fragmentContainer, dailyWeatherFragment)
fragmentTransaction.commit()
}