PagedAdapter отправляет ноль элементов списка - PullRequest
0 голосов
/ 28 октября 2018

Я попытался реализовать библиотеку пагинации для своего приложения.Я использую Livedata, RxJava и Retrofit2.В моем фрагменте, который включен в функцию нумерации страниц.Элементы очень хорошо загружаются и отображаются в программе просмотра, но, когда я отлаживаю наблюдение за pagedlist, количество отправленных списков равно 0.

Вот мои следующие коды.

Класс BookDataSource абстрактный.

abstract class BookDataSource: PageKeyedDataSource<Int, Book>() {

    val state: MutableLiveData<NetworkState> = MutableLiveData()
    private var retryCompletable: Completable? = null

    abstract var compositeDisposable: CompositeDisposable
    abstract var byblosRepo: ByblosRepo

    override fun loadInitial(params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, Book>) {
        Log.i("LOAD", "initial")
        updateState(NetworkState.LOADING)
        loadInitialRequest(byblosRepo, params, callback)

    }

    override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, Book>) {
        Log.i("LOAD", "after")
        updateState(NetworkState.LOADING)
        loadAfterRequest(byblosRepo, params, callback)
    }

    override fun loadBefore(params: LoadParams<Int>, callback: LoadCallback<Int, Book>) {
        Log.i("LOAD", "before")
    }

    fun retry() {
        if (retryCompletable != null) {
            compositeDisposable.add(retryCompletable!!
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe())
        }
    }

    fun updateState(state: NetworkState) {
        this.state.postValue(state)
    }

    fun setRetry(action: Action?) {
        retryCompletable = if (action == null) null else Completable.fromAction(action)
    }

    abstract fun loadInitialRequest(byblosRepo: ByblosRepo, params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, Book>)
    abstract fun loadAfterRequest(byblosRepo: ByblosRepo, params: LoadParams<Int>, callback: LoadCallback<Int, Book>)
}

Это реальный класс источника данных.

class AwardedBookDataSource constructor(private val awardType: String, override var byblosRepo: ByblosRepo, override var compositeDisposable: CompositeDisposable) : BookDataSource() {

    override fun loadInitialRequest(byblosRepo: ByblosRepo, params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, Book>) {
        val awardedQuery = AwardedBookRequest(awardType, ByblosApp.deviceId, "1", 0)
        compositeDisposable.add(byblosRepo.getAwardedBook(awardedQuery)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ search ->
                    callback.onResult(search.books, 1, 2)
                    updateState(NetworkState.DONE)
                }, { _ ->
                    updateState(NetworkState.ERROR)
                    setRetry(Action { loadInitial(params, callback) })
                }))
    }

    override fun loadAfterRequest(byblosRepo: ByblosRepo, params: LoadParams<Int>, callback: LoadCallback<Int, Book>) {
        val awardedQuery = AwardedBookRequest(awardType, ByblosApp.deviceId, params.key.toString(), 0)
        compositeDisposable.add(byblosRepo.getAwardedBook(awardedQuery)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ search ->
                    callback.onResult(search.books, params.key + 1)
                    updateState(NetworkState.DONE)
                }, { _ ->
                    updateState(NetworkState.ERROR)
                    setRetry(Action { loadAfter(params, callback) })
                }))
    }
}

Это абстрактный класс фабрики источника данных.

abstract class BookDataSourceFactory: DataSource.Factory<Int, Book>() {

    val bookDataSourceLiveData = MutableLiveData<BookDataSource>()

    abstract var compositeDisposable: CompositeDisposable
    abstract var byblosRepo: ByblosRepo

    override fun create(): DataSource<Int, Book> {
        val bookDataSource = createBookDataSource()
        bookDataSourceLiveData.postValue(bookDataSource)
        return bookDataSource
    }

    abstract fun createBookDataSource(): BookDataSource
}

Фактический класс фабрики источника данных

class AwardedBookDataSourceFactory(override var byblosRepo: ByblosRepo, override var compositeDisposable: CompositeDisposable): BookDataSourceFactory() {

    lateinit var awardType: String

    override fun createBookDataSource(): BookDataSource = AwardedBookDataSource(awardType, byblosRepo, compositeDisposable)
}

Моя видовая модель фрагмента

class PrixViewModel @Inject constructor(byblosRepo: ByblosRepo) : BaseViewModel() {

    lateinit var awardedBookList: LiveData<PagedList<Book>>
    private var bookDataSourceFactory: AwardedBookDataSourceFactory = AwardedBookDataSourceFactory(byblosRepo, compositeDisposable)

    fun getBookList(awardType: String = "all") {
        val config = PagedList.Config.Builder()
                .setPageSize(20)
                .setInitialLoadSizeHint(20)
                .setEnablePlaceholders(false)
                .build()
        bookDataSourceFactory.awardType = awardType
        awardedBookList = LivePagedListBuilder<Int, Book>(bookDataSourceFactory, config).build()
    }

    /*fun retry(tabPosition: Int) {
        bookDataSourceFactory.bookDataSourceLiveData.value?.retry()
    }*/

    fun getState(): LiveData<NetworkState> = Transformations.switchMap<BookDataSource, NetworkState>(bookDataSourceFactory.bookDataSourceLiveData, BookDataSource::state)

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

    /*fun replaceSubscription(lifecycleOwner: LifecycleOwner, awardType: String) {
        //awardedBookList.removeObservers(lifecycleOwner)
        getBookList(awardType)
        //bookDataSourceFactory.awardType = awardType
        //bookDataSourceFactory.bookDataSourceLiveData.value?.invalidate()
    }*/
}

Это мой фрагмент, показывающий вид рециклера

Класс PrixFragment: BaseFragment () {

@Inject
lateinit var mPrixViewModelFactory: ViewModelFactory

override fun getBindingVariable(): Int = BR.viewModel

override fun getLayoutId(): Int = R.layout.fragment_prix

private lateinit var mFragmentPrixBinding: FragmentPrixBinding

private lateinit var prixListAdapter: PrixListAdapter


companion object {
    fun newInstance(): PrixFragment {
        val args = Bundle()
        val fragment = PrixFragment()
        fragment.arguments = args
        return fragment
    }
}

override fun getViewModel(): PrixViewModel = ViewModelProviders.of(this, mPrixViewModelFactory).get(PrixViewModel::class.java)

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    mFragmentPrixBinding = getViewDataBinding()
    setUp()
    getViewModel().getBookList()
    initAdapter()
    initState()
}

private fun initState() {
    getViewModel().getState().observe(this, Observer { state ->
        getViewModel().loadingVisibility.value = if (getViewModel().listIsEmpty() && state == NetworkState.LOADING) View.VISIBLE else View.GONE
        if (!getViewModel().listIsEmpty()) {
            prixListAdapter.setState(state ?: NetworkState.DONE)
        }
    })
}

private fun initAdapter() {
    prixListAdapter = PrixListAdapter()
    mFragmentPrixBinding.apply {
        recyclerPrix.layoutManager = LinearLayoutManager(activity, RecyclerView.VERTICAL, false)
        recyclerPrix.addItemDecoration(DividerItemDecoration(activity, RecyclerView.VERTICAL))
        recyclerPrix.adapter = prixListAdapter
    }
    getViewModel().awardedBookList.observe(this, Observer {
        //THIS "IT" LIST SIZE SHOWS 0 COUNT. Why? But recyclerview notified.
        prixListAdapter.submitList(it)
    })
}

private fun setUp() {

    mFragmentPrixBinding.apply {
        tabPrix.addTab(tabPrix.newTab())
        tabPrix.addTab(tabPrix.newTab())
        tabPrix.addTab(tabPrix.newTab())
        tabPrix.addTab(tabPrix.newTab())

        changeCurrentTabFont(0)

        tabPrix.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
            override fun onTabReselected(p0: TabLayout.Tab?) {}

            override fun onTabUnselected(p0: TabLayout.Tab?) {}

            override fun onTabSelected(tab: TabLayout.Tab) {
                changeCurrentTabFont(tab.position)
                var awardType = "all"
                when (tab.position) {
                    0 -> awardType = "all"
                    1 -> awardType = "goncourt"
                    2 -> awardType = "femina"
                    3 -> awardType = "renaudot"
                }
                //viewModel?.replaceSubscription(this@PrixFragment, awardType)
                viewModel?.getBookList(awardType)
                initAdapter()
            }

        })
    }
}

private fun changeCurrentTabFont(position: Int) {
    for (i in 0 until mFragmentPrixBinding.tabPrix.tabCount) {
        val tab: TabLayout.Tab? = mFragmentPrixBinding.tabPrix.getTabAt(i)
        tab?.customView = null
        if (position != i)
            tab?.customView = getTabView(resources.getStringArray(R.array.tab_titles)[i])
        else
            tab?.customView = getSelectedTabView(resources.getStringArray(R.array.tab_titles)[i])
    }
}

private fun getTabView(title: String): TextView {
    val view: TextView = View.inflate(context, R.layout.layout_inactive_tab_font, null) as TextView
    view.text = title
    return view
}

private fun getSelectedTabView(title: String): View {
    val view: TextView = View.inflate(context, R.layout.layout_active_tab_font, null) as TextView
    view.text = title
    return view
}

}

...