Библиотека подкачки Android LiveData <PagedList <T>> запускается до завершения вызова API - PullRequest
0 голосов
/ 27 октября 2018

Уже 2 дня я пытаюсь научиться использовать новую пейджинговую библиотеку с языком Kotlin (тоже впервые)

Так что я прочитал много гида / учебника и репозитория Github (* 1003)*https://github.com/STAR-ZERO/paging-retrofit-sample) для реализации этой библиотеки подкачки и, в принципе, моя проблема в том, что мой LiveData<PagedList<Discover>> внутри моего ViewModel триггера до завершения моего вызова API, и я не знаю почему, и я чувствую, что вызов callback.onResult(it?.results.orEmpty(), null, 2) не делаетчто-нибудь

Я использую эту версию android.arch.paging:runtime:1.0.1 Репо моего проекта можно найти здесь: 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

Здесь естьмой код:

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

Ответы [ 2 ]

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

loadInitial(), loadAfter(), loadBefore() уже асинхронны. Если вы попытаетесь println(Thread.currentThread().name), вы получите arch_disk_io_0. Чтобы решить эту проблему, необходимо выполнить синхронный код, чтобы не пропустить обратный вызов.

0 голосов
/ 27 октября 2018

Ну, после многих изменений я нашел что-то, что решило проблему, но это так странно. Если я использую enqueue с Retrofit 2.3, он не будет работать, но если я сделаю .execute(), LiveData будет правильно запущен

Если у кого-то есть лучшее объяснение этой проблемы, добро пожаловать!

Редактировать: Я только что прочитал Paging library overview страницу на сайте Android, и я нашел это:

Для отображения данных с внутреннего сервера используйте синхронную версию Retrofit API для загрузки информации в ваш собственный источник данных объект.

...