Кеширование не работает в Android Paging 3 - PullRequest
1 голос
/ 16 июня 2020

Я реализовал приложение, используя учебник codelabs для новой библиотеки Paging 3, выпуск которой был на неделе go. Проблема в том, что приложение не работает в автономном режиме. Он не извлекает данные из базы данных комнат.

Ссылка на репозиторий учебного пособия: - https://github.com/googlecodelabs/android-paging

Код: -

  1. RepoDao.kt

    @Dao
    interface RepoDao {
    
       @Insert(onConflict = OnConflictStrategy.REPLACE)
       suspend fun insertAll(repos: List<Repo>)
    
       @Query("SELECT * FROM repos WHERE " +
        "name LIKE :queryString OR description LIKE :queryString " +
        "ORDER BY stars DESC, name ASC")
       fun reposByName(queryString: String): PagingSource<Int, Repo>
    
       @Query("DELETE FROM repos")
       suspend fun clearRepos()
    }
    
  2. GithubRepository.kt

    class GithubRepository(
        private val service: GithubService,
        private val database: RepoDatabase
    ) {
       fun getSearchResultStream(query: String): Flow<PagingData<Repo>> {
    
          val dbQuery = "%${query.replace(' ', '%')}%"
          val pagingSourceFactory = { database.reposDao().reposByName(dbQuery) }
    
          return Pager(
             config = PagingConfig(pageSize = NETWORK_PAGE_SIZE),
             remoteMediator = GithubRemoteMediator(
                    query,
                    service,
                    database
            ),
            pagingSourceFactory = pagingSourceFactory
          ).flow
       }
    
       companion object {
           private const val NETWORK_PAGE_SIZE = 50
       }
    }
    
  3. SearchRepositoriesViewModel.kt

    @ExperimentalCoroutinesApi
    class SearchRepositoriesViewModel(private val repository: GithubRepository) : ViewModel() {
        private var currentQueryValue: String? = null
    
        private var currentSearchResult: Flow<PagingData<Repo>>? = null
    
        fun searchRepo(queryString: String): Flow<PagingData<Repo>> {
            val lastResult = currentSearchResult
            if (queryString == currentQueryValue && lastResult != null) {
                return lastResult
            } 
            currentQueryValue = queryString
            val newResult: Flow<PagingData<Repo>> = repository.getSearchResultStream(queryString).cachedIn(viewModelScope)
            currentSearchResult = newResult
            return newResult
        }
    
    } 
    
  4. SearchRepositoriesActivity.kt

    @ExperimentalCoroutinesApi
    class SearchRepositoriesActivity : AppCompatActivity() {
    
        .....
        private lateinit var viewModel: SearchRepositoriesViewModel
        private val adapter = ReposAdapter()
    
        private var searchJob: Job? = null
    
        // this is where adapter get flow data from viewModel
        // initially this is called with **Android** as a query
        private fun search(query: String) {
            searchJob?.cancel()
            searchJob = lifecycleScope.launch {
                viewModel.searchRepo(query).collectLatest {
                    adapter.submitData(it)
                }
            }
        }
        .....
     }
    

Вывод: - Это просто показывает пустой recyclerview, когда приложение открыто в автономном режиме.

1 Ответ

1 голос
/ 16 июня 2020

Если вы можете поделиться своим кодом или как вы пришли к такому выводу, я, вероятно, мог бы помочь определить проблему немного лучше, но codelab действительно загружает данные из комнаты в ветке: step13-19_network_and_database

Здесь есть два компонента:

PagingSource: предоставляется Room путем объявления @Query с типом возвращаемого значения PagingSource, создаст PagingSource, загружаемый из Room. Эта функция вызывается в лямбде pagingSourceFactory в Pager, который ожидает новый экземпляр при каждом вызове.

RemoteMediator: load() вызывается при граничных условиях, когда в локальном кеше нет данных, это приведет к получить из сети и сохранить в базе данных Room, которая автоматически распространяет обновления для реализации PagingSource, сгенерированной Room.

Еще одна проблема, с которой вы можете столкнуться, может быть связана с loadStateListener/Flow, по сути, кодовая таблица показывает ошибку состояние, проверяя наличие CombinedLoadStates.refresh, но это всегда относится к состоянию загрузки RemoteMediator, когда доступно, и если вы хотите отображать локально кэшированные данные, даже при выходе RemoteMediator ошибок, вам необходимо отключить скрытие список в этом случае.

Обратите внимание, что вы можете получить доступ к индивидуальному LoadState с помощью CombinedLoadStates.source или CombinedLoadStates.mediator.

Надеюсь, этого достаточно, чтобы помочь вам, но трудно угадать ваш проблема без более конкретного примера / информации о том, что вы видите. основная проблема с библиотекой, которую я ищу здесь: https://android-review.googlesource.com/c/platform/frameworks/support/+/1341068

Edit2: Сейчас это исправлено и будет выпущено с alpha02.

...