具有ViewModel和实时数据的ViewPager,所有6个标签数据都被最后一个标签数据替换 [英] ViewPager with viewmodel and live data , all 6 tabs data is replaced by last tab data
问题描述
我正在使用6 tabs
的ViewPager
,其中只有一个片段TimesListFragment
I am working on a ViewPager
with 6 tabs
where it has only one fragment TimesListFragment
根据传递给TimesListFragment
的参数,它调用api.科学,技术,旅行等
Depending on the arguments passed to TimesListFragment
it calls api eg; science , technology, travel etc
对于我的应用程序,我一直遵循Google的GithubBrowserSample
I have followed Google's GithubBrowserSample
for my app
我有TimesListFragment
-> TimesViewModel
-> TimesRepository
有6个标签,当我点击api时,所有标签显示的结果与最后一个argument
There are 6 tabs , when I hit the api all the tabs show the same result which if of the last argument
StoriesPagerAdapter.kt
class StoriesPagerAdapter(fragmentManager: FragmentManager?)
:FragmentStatePagerAdapter(fragmentManager){
private val sections= arrayListOf("science","technology","business","world","movies","travel")
override fun getItem(position: Int): Fragment {
return TimesListFragment.newInstance(sections[position])
}
override fun getCount(): Int {
return sections.size
}
override fun getPageTitle(position: Int): CharSequence? {
return sections[position]
}
}
问题:所有选项卡均显示travel
参数的数据
issue : all tabs shows data of travel
arguments
TimesViewModel
class TimesViewModel @Inject constructor(private val timesRepository: TimesRepository) :
ViewModel() {
lateinit var data: LiveData<Resource<TimesStoriesResponse>>
fun fetchStories(section:String): LiveData<Resource<TimesStoriesResponse>> {
data = timesRepository.loadStories(section)
return data
}
}
TimesRepository.kt
class TimesRepository @Inject constructor(private val apiService: ApiService,
private val timesDao: TimesDao,
private val appExecutors: AppExecutors) {
private val repoListRateLimit = RateLimiter<String>(10, TimeUnit.MINUTES)
fun loadStories(section:String): LiveData<Resource<TimesStoriesResponse>> {
return object : NetworkBoundResource<TimesStoriesResponse, TimesStoriesResponse>(appExecutors) {
override fun saveCallResult(item: TimesStoriesResponse) {
timesDao.insert(item)
}
override fun shouldFetch(data: TimesStoriesResponse?): Boolean {
return data == null || repoListRateLimit.shouldFetch(section)
}
override fun loadFromDb() = timesDao.load()
override fun createCall() = apiService.getTopStories(section,ConfigConstant.TIMES_KEY)
override fun onFetchFailed() {
repoListRateLimit.reset(section)
}
}.asLiveData()
}
ApiService.kt
interface ApiService {
@GET("svc/topstories/v2/{section}.json?")
fun getTopStories(@Path ("section") section:String,@Query("api-key") apiKey:String)
:LiveData<ApiResponse<TimesStoriesResponse>>
}
TimesListFragment.kt
private fun initViewModel() {
viewModel = ViewModelProviders.of(this, viewModelFactory).get(section,TimesViewModel::class.java)
}
private fun initData() {
viewModel?.fetchStories(section)?.observe(this, Observer {
when (it?.status) {
Status.LOADING -> {
showLoading(true)
showError(false,null)
}
Status.SUCCESS -> {
showLoading(false)
showError(false,null)
showSuccessData(it.data)
}
Status.ERROR -> {
showLoading(false)
showError(true,it.message)
}
}
})
}
注意:两种方法都在TimesListFragmnet
note : both methods are called in onViewCreated() of TimesListFragmnet
推荐答案
这应该是由于您的ViewModel
而发生的.
This should be happening due to your ViewModel
.
通常,由于ViewModel
的工作方式,每个Activity
或Fragment
有一个ViewModel
.使用ViewModel
的主要好处之一是它的生命周期与Fragment
的生命周期完全分开,因此,您的Fragment
可以被破坏并重新创建多次,并且仍然可以恢复当前版本. ViewModel
中存储的数据.
Typically, there's one ViewModel
per Activity
or Fragment
, due to the way a ViewModel
is designed to work. One of the major benefits in using a ViewModel
is that it's lifecycle is completely separate from the lifecycle of your Fragment
, therefore, your Fragment
can be destroyed and recreated multiple times and you'll still be able to restore current data that's stored in your ViewModel
.
因此,这意味着使用从ViewModelProviders
获取ViewModel
的典型代码,您将获取完全相同的ViewModel
.
Therefore, this means that with the typical code to fetch the ViewModel
from the ViewModelProviders
, you'll be fetching the exact same ViewModel
.
通常,这不会引起问题,但是在您的ViewPager
中,您正在重用相同的TimesListFragment
,这很可能是 调用相同的ViewModel
,因此每个片段显示相同的数据.
Typically, this won't cause a problem, but in your ViewPager
, you're reusing the same TimesListFragment
which is most likely calling up the same ViewModel
, therefore causing each fragment to show the same data.
解决方案是使用:
ViewModelProviders.of(this).get(KEY, TimesViewModel::class.java)
请注意用于区分需要获取的ViewModel的KEY.因此,通过将ViewPager
中的位置用作唯一键,您应该能够为每个TimesListFragment
具有唯一的ViewModel
.
Note the KEY which is used to differentiate between the ViewModels that needs to be fetched. So by using the positions in the ViewPager
as a unique key, you should be able to have a unique ViewModel
for each TimesListFragment
.
这篇关于具有ViewModel和实时数据的ViewPager,所有6个标签数据都被最后一个标签数据替换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!