我已经使用代码实验室教程为新的 Paging 3 库实现了应用程序,该库于一周前发布。 问题是应用程序无法在离线模式下工作。它不会从 Room 数据库中检索数据。
教程 repo 链接:- https://github.com/googlecodelabs/android-paging
代码:-
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() }
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 } }
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 } }
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。
最佳答案
如果您能够分享您的代码或您是如何得出该结论的,我可能会帮助您更好地查明问题,但代码实验室确实会从分支上的 Room 加载数据:step13-19_network_and_database
这里有两个组件:
PagingSource
:由 Room 通过声明一个带有 PagingSource
返回类型的 @Query
提供,将创建一个 PagingSource
从 Room 加载。此函数在 Pager
的 pagingSourceFactory
lambda 中调用,每次调用都需要一个新实例。
RemoteMediator
:load()
在本地缓存没有数据的边界条件下调用,这将从网络获取并存储在 Room 数据库中,自动传播更新由 Room 生成的 PagingSource
实现。
您可能会看到的另一个问题可能与 loadStateListener/Flow
相关,本质上,Codelab 通过检查 CombinedLoadStates.refresh
来显示错误状态,但这总是延迟到 RemoteMediator
可用时的加载状态,如果您想显示本地缓存的数据,即使 RemoteMediator
出错,您也需要禁用列表隐藏在那种情况下。
请注意,您可以使用 CombinedLoadStates.source
或 CombinedLoadStates.mediator
访问单个 LoadState
。
希望这足以帮助您,但如果没有关于您所看到的内容的更具体示例/信息,很难猜测您的问题。
编辑:虽然以上仍然是需要检查的好东西,但看起来我正在寻找的库存在潜在问题:https://android-review.googlesource.com/c/platform/frameworks/support/+/1341068
Edit2:现在已修复,将与 alpha02 一起发布。
关于android - 缓存在 Android Paging 3 中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62401969/