使用 postDelayed 延迟打开片段是一种好习惯吗?
Is a good practice to use postDelayed for delay the opening of fragment?
我正在制作一个基于 TMDB 数据库的应用程序。我有一个装有最新电视节目的 recyclerView。当我点击一张海报时,我调用 TMDB api,获取一个包含节目信息的对象并打开一个加载了该对象数据的片段。
问题是当我返回并点击其他电视节目时,当片段再次打开时它会简要显示我点击的上一个电视节目的信息。
我认为问题在于我正在使用 livedata 在 viewmodel 和 fragment 之间传递数据,并且它正在加载 livedata 中已有的数据。
所以我用它来稍微延迟片段的打开:
HomeFragment - OnCLick
viewmodel.getShowDetails(showId)
val mHandler = Handler()
val monitor = Runnable {
Navigation.findNavController(view)
.navigate(HomeFragmentDirections.actionHomeToShowDetail())
}
mHandler.postDelayed(monitor, 300)
视图模型
private var showMutable = MutableLiveData<ShowDetails>()
fun getShowData(id: Int) {
TmdbRepository.getDetails(id) // This returns an RxJava Observable
.observeOn(Schedulers.io())
.doOnError(Throwable::printStackTrace)
.subscribe {
showMutable.postValue(it)
}
}
fun getShow(): LiveData<ShowDetails> {
return showMutable
}
ShowDetailFragment
override fun onCreateView(
viewModel.getShow().observe(viewLifecycleOwner, Observer {
mShow = it
setData(mShow) // this fills the textviews, images, etc
})
}
用这个方法好不好?或者也许我应该使用其他东西在片段和视图模型之间传递数据而不是实时数据?
谢谢。
可惜用postDelayed不好.
由于您的 ViewModel 是共享的,如果以前的电影详细信息,您的 MutuableLiveData 将保存数据。
解决这个问题可能有两种形式:
第一个解决方案,使用StateUi,包括加载,成功,失败如下:
sealed class StateUi {
data class Success(val data: Any) : StateUi()
object Loading : StateUi()
class Error(val throwable: Throwable) : StateUi()
}
另外,在doOnSubscribe()中添加StateUi.Loading如下:
TmdbRepository.getDetails(id) // This returns an RxJava Observable
.observeOn(Schedulers.io())
.doOnSubscribe(StateUi.Loading)
.doOnError(Throwable::printStackTrace)
.subscribe {
showMutable.postValue(it)
}
按照以下方式制作您的 MutuableLiveData
private var showMutable = MutableLiveData<StateUi<ShowDetails>>()
并在您的片段中观察,这将如何解决您的问题?
因为你正在观察状态,所以默认情况下 MutuableLiveData 的状态将是正在加载,而不是保存上一部电影的数据。
第二种解决方案,
为每个片段创建单独的 ViewModel class。但我确实推荐第一种解决方案。
我正在制作一个基于 TMDB 数据库的应用程序。我有一个装有最新电视节目的 recyclerView。当我点击一张海报时,我调用 TMDB api,获取一个包含节目信息的对象并打开一个加载了该对象数据的片段。
问题是当我返回并点击其他电视节目时,当片段再次打开时它会简要显示我点击的上一个电视节目的信息。
我认为问题在于我正在使用 livedata 在 viewmodel 和 fragment 之间传递数据,并且它正在加载 livedata 中已有的数据。 所以我用它来稍微延迟片段的打开:
HomeFragment - OnCLick
viewmodel.getShowDetails(showId)
val mHandler = Handler()
val monitor = Runnable {
Navigation.findNavController(view)
.navigate(HomeFragmentDirections.actionHomeToShowDetail())
}
mHandler.postDelayed(monitor, 300)
视图模型
private var showMutable = MutableLiveData<ShowDetails>()
fun getShowData(id: Int) {
TmdbRepository.getDetails(id) // This returns an RxJava Observable
.observeOn(Schedulers.io())
.doOnError(Throwable::printStackTrace)
.subscribe {
showMutable.postValue(it)
}
}
fun getShow(): LiveData<ShowDetails> {
return showMutable
}
ShowDetailFragment
override fun onCreateView(
viewModel.getShow().observe(viewLifecycleOwner, Observer {
mShow = it
setData(mShow) // this fills the textviews, images, etc
})
}
用这个方法好不好?或者也许我应该使用其他东西在片段和视图模型之间传递数据而不是实时数据?
谢谢。
可惜用postDelayed不好.
由于您的 ViewModel 是共享的,如果以前的电影详细信息,您的 MutuableLiveData 将保存数据。
解决这个问题可能有两种形式:
第一个解决方案,使用StateUi,包括加载,成功,失败如下:
sealed class StateUi {
data class Success(val data: Any) : StateUi()
object Loading : StateUi()
class Error(val throwable: Throwable) : StateUi()
}
另外,在doOnSubscribe()中添加StateUi.Loading如下:
TmdbRepository.getDetails(id) // This returns an RxJava Observable
.observeOn(Schedulers.io())
.doOnSubscribe(StateUi.Loading)
.doOnError(Throwable::printStackTrace)
.subscribe {
showMutable.postValue(it)
}
按照以下方式制作您的 MutuableLiveData
private var showMutable = MutableLiveData<StateUi<ShowDetails>>()
并在您的片段中观察,这将如何解决您的问题?
因为你正在观察状态,所以默认情况下 MutuableLiveData 的状态将是正在加载,而不是保存上一部电影的数据。
第二种解决方案, 为每个片段创建单独的 ViewModel class。但我确实推荐第一种解决方案。