Использование библиотеки подкачки Android для отображения отфильтрованных результатов из тех же 2 загруженных фрагментов в ViewPager с FragmentPagerAdapter - PullRequest
0 голосов
/ 15 февраля 2019

У меня есть одно приложение активности, которое сосредоточено вокруг фрагмента, который будет перечислять данные из онлайн API.Я использую один и тот же фрагмент в приложении, фильтруя данные по мере необходимости.

Фильтрация выполняется путем передачи параметров через Factory в DataSource.Все это прекрасно работает, если у меня загружен только один фрагмент.Я могу хорошо фильтровать и искать.

Проблемы начинаются при попытке загрузить несколько фрагментов в ViewPager.Например, Фрагмент A - фильтруется для отображения активных элементов. Фрагмент B - фильтруется для отображения элементов с истекшим сроком. Оба должны отображаться в ViewPager с использованием FragmentPagerAdapter.Когда я запускаю приложение, оба Фрагмента будут отфильтрованы для просроченных элементов (последний фрагмент добавлен в viewpager). Кажется, параметры, которые Фрагмент A, установленный в DataSource, немедленно перезаписываются Фрагментом B. Фрагмент loadInitial работает, как и должно, но loadAfter используетпараметры из фрагмента B.

также должны помнить, что если я аннулирую () источник данных, он возвращает правильные отфильтрованные данные без проблем.(поэтому при загрузке мои параметры перезаписываются, а loadAfter использует неверный параметр)

Пробовал связываться с Обозревателем с помощью getViewLifecycleOwner (), пытаясь выяснить, правильно ли я называю DataSource, - это пробовал различные ViewPagerАдаптеры FragmentStatePagerAdapter и FragmentPagerAdapter.

Все проверки показывают, что DataSource получает правильный параметр, а затем почти сразу же перезаписывают его.

Так что вопрос в том, является ли вызов PageKeyedDataSource не уникальным для фрагмента, вызывающего его?Почему мои переменные перезаписываются другим фрагментом.

Может кто-нибудь сказать, где я должен искать решение этой проблемы.

Примечание: у меня есть три фрагмента, загруженных с использованием FragmentStatePagerAdapter, из которых 2 из 3 являютсяОдин и тот же фрагмент. Вызывается с разными параметрами.Он работает нормально, потому что с тремя загруженными фрагментами FragmentStatePagerAdapter, по-видимому, не инициализирует 3-й фрагмент до тех пор, пока все не будет загружено, поэтому он не отключится по другому фрагменту.

1 Ответ

0 голосов
/ 15 февраля 2019

Я столкнулся с той же проблемой просмотра пейджер загружает два фрагмента, следующий фрагмент переопределяет значение.Вот как я это сделал.

Во фрагменте я устанавливаю список для просмотра модели.

companion object {
private const val ARG_SECOND = "arg_second"

@JvmStatic
fun newInstance(second: Array<Pair<String, String>>): PlaceholderFragment {
    return PlaceholderFragment().apply {
        arguments = Bundle().apply {
            putString(ARG_SECOND,second[0].second)
        }
    }
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProviders.of(this).get(PageViewModel::class.java).apply {
    setListId(arguments?.getString(ARG_SECOND) ?: "")
}
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    btn.setOnClickListener {
        viewModel.setListId("my id")
        viewModel.videosList.value?.dataSource?.invalidate()       
    }
}

В модели представления я создаю метод setListId:

class PageViewModel(application: Application) : AndroidViewModel(application) 
{

//paging
private val networkService = NetworkService.getService()
var videosList: LiveData<PagedList<Item>>
private val compositeDisposable = CompositeDisposable()
private val pageSize = 50
private val videosDataSourceFactory: VideosDataSourceFactory

init {
videosDataSourceFactory = VideosDataSourceFactory(compositeDisposable, 
networkService)
    val config = PagedList.Config.Builder()
        .setPageSize(pageSize)
        .setInitialLoadSizeHint(pageSize)
        .setEnablePlaceholders(false)
        .build()
    videosList = LivePagedListBuilder<String, Item>(videosDataSourceFactory, 
config).build()
}

fun getState(): LiveData<State> = Transformations.switchMap<VideosDataSource,
        State> 
(videosDataSourceFactory.videosDataSourceLiveData,VideosDataSource::state)

fun retry() {
    videosDataSourceFactory.videosDataSourceLiveData.value?.retry()
}
fun setListId(listId: String){
    videosDataSourceFactory.listId = listId
}


override fun onCleared() {
    super.onCleared()
    compositeDisposable.dispose()
}

fun listIsEmpty(): Boolean {
    return videosList.value?.isEmpty() ?: true
}
}

В фабрике источников данных я создаю переменную:

val videosDataSourceLiveData = MutableLiveData<VideosDataSource>()
lateinit var listId:String

override fun create(): DataSource<String, Item> {
val videosDataSource = VideosDataSource(networkService, 
compositeDisposable,listId)
videosDataSourceLiveData.postValue(videosDataSource)
return videosDataSource
}

А затем получить его через конструктор источника данных здесь:

class VideosDataSource(
private val networkService: NetworkService,
private val compositeDisposable: CompositeDisposable,
private val listId: String
): PageKeyedDataSource<String, Item>() {
var state: MutableLiveData<State> = MutableLiveData()
private var retryCompletable: Completable? = null

override fun loadInitial(params: LoadInitialParams<String>, callback: 
LoadInitialCallback<String, Item>) {
updateState(State.LOADING)
compositeDisposable.add(
        networkService.getPlaylistVideos(listId
        ,""
        ,Constants.API_KEY)
        .subscribe( { response ->
            updateState(State.DONE)
            callback.onResult(response.items, response.prevPageToken, 
response.nextPageToken)
        },
                {
                    updateState(State.ERROR)
                    setRetry(Action { loadInitial(params,callback) })
                }
        )
)
}
...