简体   繁体   中英

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

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)
    }
}

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM