在 PageKeyedDataSource 中调用挂起函数的正确方法
Right way to call suspend function in a PageKeyedDataSource
我遇到了一个问题。所以基本上我正在实现一个分页列表,其中包含通过网络带来的数据。
我用的是:
改造挂起
带实时数据的 MVVM
PageKeyedDataSource、DataSource.Factory 和 PagedListAdapter
现在为了执行挂起函数,我将协程作用域(视图模型作用域)传递给数据源的构造函数。
一切正常,分页工作但有一个小问题,submitList() 这是在实际更新实时数据之前调用更新数据的适配器方法所以它的大小为 0,因此,不会调用 DiffUtil.ItemCallback 来为列表设置动画。列表已更新,但没有动画。
我想如果我在 PageKeyedDataSource.loadInitial 中用简化的日志向您展示 2 段代码会更容易:
使用协程:
// the viewModel scope
scope.launch(getJobErrorHandler()) {
networkState.postValue(NetworkState.Loading)
Log.d(LOG_TAG, "Loading data")
val result = withContext(withContext(Dispatchers.IO) {
// retrofit suspend fun
service.getSearchUsers(query, ApiConstants.DEFAULT_SEARCH_LIMIT, newOffset)
}
Log.d(LOG_TAG, "Finished loading")
callback.onResult(result.users, result.next)
networkState.postValue(NetworkState.SUCCESS)
}
在片段中
viewModel.users.observe(this@SearchFragment, Observer {
adapter.submitList(it)
Log.d(LOG_TAG, "submit list with count ${it.size}")
})
日志:
D/MMF_APP: Loading data
D/MMF_APP: submitList() with count 0
D/MMF_APP: Finished loading
没有协程:
networkState.postValue(NetworkState.Loading)
Log.d(LOG_TAG, "Loading data")
// mock method, non suspend
service.mockGetSearchUsers(query, ApiConstants.DEFAULT_SEARCH_LIMIT, newOffset)
Log.d(LOG_TAG, "Finished loading")
callback.onResult(result.users, result.next)
networkState.postValue(NetworkState.SUCCESS)
在片段中
viewModel.users.observe(this@SearchFragment, Observer {
adapter.submitList(it)
Log.d(LOG_TAG, "submit list with count ${it.size}")
})
日志:
D/MMF_APP: Loading data
D/MMF_APP: Finished loading
D/MMF_APP: submitList() with count 5
请注意,在这两种情况下,分页效果都很好,唯一的区别是使用协程时,最初将大小为 0 的列表设置为适配器,正如我提到的,DiffUtil.ItemCallback没有被调用。
val result = withContext(withContext(Dispatchers.IO) {
// retrofit suspend fun
service.getSearchUsers(query, ApiConstants.DEFAULT_SEARCH_LIMIT, newOffset)
}
尝试用协程的旧方法替换上面的代码:\
async {
}.await()
只是为了确保它确实在等待。
总之可能是分页库的问题,满是bug...
你也分页列表更新视图模型 livedata 吗?是吗?
我遇到了一个问题。所以基本上我正在实现一个分页列表,其中包含通过网络带来的数据。
我用的是:
改造挂起
带实时数据的 MVVM
PageKeyedDataSource、DataSource.Factory 和 PagedListAdapter
现在为了执行挂起函数,我将协程作用域(视图模型作用域)传递给数据源的构造函数。
一切正常,分页工作但有一个小问题,submitList() 这是在实际更新实时数据之前调用更新数据的适配器方法所以它的大小为 0,因此,不会调用 DiffUtil.ItemCallback 来为列表设置动画。列表已更新,但没有动画。
我想如果我在 PageKeyedDataSource.loadInitial 中用简化的日志向您展示 2 段代码会更容易:
使用协程:
// the viewModel scope
scope.launch(getJobErrorHandler()) {
networkState.postValue(NetworkState.Loading)
Log.d(LOG_TAG, "Loading data")
val result = withContext(withContext(Dispatchers.IO) {
// retrofit suspend fun
service.getSearchUsers(query, ApiConstants.DEFAULT_SEARCH_LIMIT, newOffset)
}
Log.d(LOG_TAG, "Finished loading")
callback.onResult(result.users, result.next)
networkState.postValue(NetworkState.SUCCESS)
}
在片段中
viewModel.users.observe(this@SearchFragment, Observer {
adapter.submitList(it)
Log.d(LOG_TAG, "submit list with count ${it.size}")
})
日志:
D/MMF_APP: Loading data
D/MMF_APP: submitList() with count 0
D/MMF_APP: Finished loading
没有协程:
networkState.postValue(NetworkState.Loading)
Log.d(LOG_TAG, "Loading data")
// mock method, non suspend
service.mockGetSearchUsers(query, ApiConstants.DEFAULT_SEARCH_LIMIT, newOffset)
Log.d(LOG_TAG, "Finished loading")
callback.onResult(result.users, result.next)
networkState.postValue(NetworkState.SUCCESS)
在片段中
viewModel.users.observe(this@SearchFragment, Observer {
adapter.submitList(it)
Log.d(LOG_TAG, "submit list with count ${it.size}")
})
日志:
D/MMF_APP: Loading data
D/MMF_APP: Finished loading
D/MMF_APP: submitList() with count 5
请注意,在这两种情况下,分页效果都很好,唯一的区别是使用协程时,最初将大小为 0 的列表设置为适配器,正如我提到的,DiffUtil.ItemCallback没有被调用。
val result = withContext(withContext(Dispatchers.IO) {
// retrofit suspend fun
service.getSearchUsers(query, ApiConstants.DEFAULT_SEARCH_LIMIT, newOffset)
}
尝试用协程的旧方法替换上面的代码:\
async {
}.await()
只是为了确保它确实在等待。
总之可能是分页库的问题,满是bug...
你也分页列表更新视图模型 livedata 吗?是吗?