Android Paging Library LiveData<PagedList<T>> is triggered before the end of the api call

a 夏天 提交于 2019-12-06 10:21:33

问题


It's been 2 days I'm trying to learn how to use the new Paging Library with the Kotlin Language (first time too)

So I've read many guide / tutorial and Github repo (https://github.com/STAR-ZERO/paging-retrofit-sample) for implementing this paging library and basically my trouble is my LiveData<PagedList<Discover>> inside my ViewModel is trigger before my api call is ending and I don't know why and I feel the call callback.onResult(it?.results.orEmpty(), null, 2) doesn't do anything

I'm using this version android.arch.paging:runtime:1.0.1 You can find the repo of my project here : https://github.com/florian-do/TMDB

logcat :

D/DataSourceFactory: : create()
D/SequentialDataSource: loadInitial:
D/Interceptor: https://api.themoviedb.org/3/discover/movie?api_key=??
D/MainFragment: : observe 0
D/SequentialDataSource: response code -> 200
D/SequentialDataSource: list size: 20

Here there is my code :

Fragment.kt

    val adapter = DiscoverAdapter(context!!, diffCallBack)
    binding.rvFeed.layoutManager = GridLayoutManager(context, 3)
    binding.rvFeed.setHasFixedSize(true)
    binding.rvFeed.adapter = adapter

    viewModel.data.observe(this, Observer {
        Log.d(TAG, ": observe "+it?.size)
    })

MainViewModel.kt

class MainViewModel : ViewModel() {

    var amount = ObservableField<String>()
    val data : LiveData<PagedList<Discover>>

    init {
        val config = PagedList.Config.Builder()
                .setPageSize(20)
                .setEnablePlaceholders(false)
                .build()

        val api : DiscoverService = App.retrofit.create(DiscoverService::class.java)
        val dataSourceFactory = DataSourceFactory(api)

        data = LivePagedListBuilder(dataSourceFactory, config).build()
    }
}

DataSourceFactory.kt

class DataSourceFactory(api: DiscoverService) : DataSource.Factory<Int, Discover>() {
    val source = SequentialDataSource(api)

    override fun create(): DataSource<Int, Discover> {
        return source
    }
}

SequentialDataSource.kt

class SequentialDataSource(val api : DiscoverService) : PageKeyedDataSource<Int, Discover>() {

    private val TAG = "SequentialDataSource"

    override fun loadInitial(params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, Discover>) {
        Log.d(TAG, "loadInitial: ")
        api.getDiscover(TMDBClient.API_KEY).enqueue(object : Callback<DiscoverReponse> {
            override fun onFailure(call: Call<DiscoverReponse>, t: Throwable) {
                Log.d(TAG, ": FAIL")
            }

            override fun onResponse(call: Call<DiscoverReponse>, response: Response<DiscoverReponse>) {
                Log.d(TAG, ": response code -> "+response.code())
                val it = response.body();
                Log.d(TAG, "list size: "+it?.results?.size)

                response.body()?.let {
                    callback.onResult(it.results, null, 2)
                }
            }

        })

    }

    override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, Discover>) {
        Log.d(TAG, "loadAfter: "+params.key)

    }

    override fun loadBefore(params: LoadParams<Int>, callback: LoadCallback<Int, Discover>) {
        Log.d(TAG, "loadBefore: "+params.key)
    }
}

回答1:


Well, after many changed i've found something who fix the problem but it's so weird. If I use enqueue with Retrofit 2.3 it will doesn't work but if i do a .execute() the LiveData is correctly triggered

If someone have a better explanation of this problem your very welcome !

Edit : I've just read the Paging library overview page on android website and i found this :

To display data from a backend server, use the synchronous version of the Retrofit API to load information into your own custom DataSource object.




回答2:


loadInitial(), loadAfter(), loadBefore() are already asynchronous. If you try to println(Thread.currentThread().name) you will get arch_disk_io_0. To solve this you need to execute code like it's synchronous in order to not miss the callback. You will miss the callback if you switch threads, library is already doing it.



来源:https://stackoverflow.com/questions/53016777/android-paging-library-livedatapagedlistt-is-triggered-before-the-end-of-the

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!