android / architecture-components-samples

Samples for Android Architecture Components.
https://d.android.com/arch
Apache License 2.0
23.45k stars 8.28k forks source link

PagingSource returns null from room database. #862

Closed teyyihan closed 4 years ago

teyyihan commented 4 years ago

When i try to return List , it returns correctly. But when i try to return PagingSource<Int, MyObject> , it always returns null. When i debugged it, it says "lazy value not initialized yet". Even though i dont have a lazy reference.

This is with PagingSource: image

This is with List<>: image

dlam commented 4 years ago

Can you share the code you are debugging?

teyyihan commented 4 years ago

Of course. In my main fragment i have search function just like Codelab example: private fun search() { searchJob?.cancel() searchJob = lifecycleScope.launch { viewModel.searchRepo().collectLatest { Log.d("teooo", "search: executed") adapter.submitData(it) } } }

In viewmodel: `private var currentSearchResult: Flow<PagingData>? = null

fun searchRepo(): Flow<PagingData<CharacterModel>> {

    val newResult: Flow<PagingData<CharacterModel>> = characterRepo.getCharacters()
        .cachedIn(viewModelScope)
    currentSearchResult = newResult
    return newResult
}`

In repository: ` fun getCharacters(): Flow<PagingData> {

    val pagingSourceFactory =  { database.characterDao().getAllCharacters()}

    return Pager(
        config = PagingConfig(pageSize = 20),
        remoteMediator = CharacterRemoteMediator(
                service = api,
            database = database
        ),
        pagingSourceFactory = pagingSourceFactory
    ).flow
}`

In remoteMediator: `override suspend fun load(loadType: LoadType, state: PagingState<Int, CharacterModel>): MediatorResult { try {

        val apiResponse = service.getCharacters(1)
        apiResponse.results.forEach {
            it.run {
                this.nextKey = 2
                this. prevKey = null
            }
            database.characterDao().insertAllCharacters(apiResponse.results)
        }

        return MediatorResult.Success(true)
    } catch (e: Exception) {
        return MediatorResult.Error(e)
    }
}`

And lastly in my DAO: @Query("SELECT * FROM character_table ") fun getAllCharacters(): PagingSource<Int, CharacterModel>

I'm pretty sure datas are saved. I double checked via com.amitshekhar.android:debug-db library. When i run search() function, it's expected to populate the ui, but it doesn't. When i try to return livedata and then submit data to adapter, it works. Just like paging library 2.0

teyyihan commented 4 years ago

I feel so dumb. My problem was not about Paging 3.0 at all. I was using viewbinding and couldn't access the recyclerview. I don't know why it didn't throw an error but problem was not about this library.

dlam commented 4 years ago

No problem! Glad you fixed it!

I feel dumb all the time so you're not alone there :slightly_smiling_face: