Android Paging 3.0 加载方法无效
Android Paging 3.0 load method not working
我正在尝试实现 android 分页 3.0 库,但我遇到了 .load 方法不起作用的问题,起初我以为适配器 submitData 或 layoutManager 不起作用,因为我确实得到了响应来自 LoadResult.Page,但现在进一步观察时,它有点停止工作了
这是我的代码
1- 片段
private fun initAdapter() {
searchAdapter = SearchItemsAdapter {
//item clicked
}
val gridLayoutManager = GridLayoutManager(requireContext(), 2)
binding?.layoutManager = gridLayoutManager
binding?.searchAdapter = searchAdapter
}
private fun startSearch() {
searchJob?.cancel()
searchJob = viewLifecycleOwner.lifecycleScope.launch {
searchViewModel?.getSearchResults("phone")?.collectLatest {
searchAdapter?.submitData(it)
}
}
}
2- ViewModel
fun getSearchResults(query: String): Flow<PagingData<ItemModel>> {
val lastResult = currentSearchResult
if (query == currentQueryValue && lastResult != null) {
return lastResult
}
currentQueryValue = query
val newResult: Flow<PagingData<ItemModel>> = searchRepository.getSearchResults(query)
.cachedIn(viewModelScope)
currentSearchResult = newResult
return newResult
}
3- SearchRepository
fun getSearchResults(query: String): Flow<PagingData<ItemModel>> {
return Pager(
config = PagingConfig(
pageSize = 10
),
pagingSourceFactory = { SearchPagingSource(client, query) }
).flow
}
4- PagingSource
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, ItemModel> {
val position: Int = params.key ?: 1
return try {
val response: SearchResponse = service.getSearchResult(query, position)
val items = response.metadata.results
val nextKey = if (items.isEmpty()) {
null
} else {
position + 1
}
LoadResult.Page(
data = items,
prevKey = if (position == 1) null else position - 1,
nextKey = nextKey
)
} catch (exception: IOException) {
return LoadResult.Error(exception)
} catch (exception: HttpException) {
return LoadResult.Error(exception)
}
}
5- 适配器
override fun onBindViewHolder(holder: SearchItemsViewHolder, position: Int) {
val item = getItem(position)
if (item != null) {
holder.binding.item = item
holder.itemView.setOnClickListener {
itemClickCallback(item)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchItemsViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val binding = SearchItemLayoutBinding.inflate(layoutInflater, parent, false)
return SearchItemsViewHolder(binding)
}
companion object {
private val diffCallBack = object : DiffUtil.ItemCallback<ItemModel>() {
override fun areItemsTheSame(oldItem: ItemModel, newItem: ItemModel): Boolean =
oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: ItemModel, newItem: ItemModel): Boolean =
oldItem == newItem
}
}
我发现了我遇到的问题
1- 我没有从片段的 onViewCreated 方法调用 startSearch 方法,这对 API 调用没有帮助
2- XML 中的 recyclerView 具有 wrap_content 而不是 0dp 作为高度
对我来说,我的数据class是
data class Score(
val userId: String,
val username: String,
val avatarPath: String,
val score: Long,
)
我改成了
data class Score(
var userId: String? = null,
var username: String? = null,
var avatarPath: String? = null,
var score: Long? = null,
)
现在可以使用了!!
我正在尝试实现 android 分页 3.0 库,但我遇到了 .load 方法不起作用的问题,起初我以为适配器 submitData 或 layoutManager 不起作用,因为我确实得到了响应来自 LoadResult.Page,但现在进一步观察时,它有点停止工作了
这是我的代码
1- 片段
private fun initAdapter() {
searchAdapter = SearchItemsAdapter {
//item clicked
}
val gridLayoutManager = GridLayoutManager(requireContext(), 2)
binding?.layoutManager = gridLayoutManager
binding?.searchAdapter = searchAdapter
}
private fun startSearch() {
searchJob?.cancel()
searchJob = viewLifecycleOwner.lifecycleScope.launch {
searchViewModel?.getSearchResults("phone")?.collectLatest {
searchAdapter?.submitData(it)
}
}
}
2- ViewModel
fun getSearchResults(query: String): Flow<PagingData<ItemModel>> {
val lastResult = currentSearchResult
if (query == currentQueryValue && lastResult != null) {
return lastResult
}
currentQueryValue = query
val newResult: Flow<PagingData<ItemModel>> = searchRepository.getSearchResults(query)
.cachedIn(viewModelScope)
currentSearchResult = newResult
return newResult
}
3- SearchRepository
fun getSearchResults(query: String): Flow<PagingData<ItemModel>> {
return Pager(
config = PagingConfig(
pageSize = 10
),
pagingSourceFactory = { SearchPagingSource(client, query) }
).flow
}
4- PagingSource
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, ItemModel> {
val position: Int = params.key ?: 1
return try {
val response: SearchResponse = service.getSearchResult(query, position)
val items = response.metadata.results
val nextKey = if (items.isEmpty()) {
null
} else {
position + 1
}
LoadResult.Page(
data = items,
prevKey = if (position == 1) null else position - 1,
nextKey = nextKey
)
} catch (exception: IOException) {
return LoadResult.Error(exception)
} catch (exception: HttpException) {
return LoadResult.Error(exception)
}
}
5- 适配器
override fun onBindViewHolder(holder: SearchItemsViewHolder, position: Int) {
val item = getItem(position)
if (item != null) {
holder.binding.item = item
holder.itemView.setOnClickListener {
itemClickCallback(item)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchItemsViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val binding = SearchItemLayoutBinding.inflate(layoutInflater, parent, false)
return SearchItemsViewHolder(binding)
}
companion object {
private val diffCallBack = object : DiffUtil.ItemCallback<ItemModel>() {
override fun areItemsTheSame(oldItem: ItemModel, newItem: ItemModel): Boolean =
oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: ItemModel, newItem: ItemModel): Boolean =
oldItem == newItem
}
}
我发现了我遇到的问题
1- 我没有从片段的 onViewCreated 方法调用 startSearch 方法,这对 API 调用没有帮助
2- XML 中的 recyclerView 具有 wrap_content 而不是 0dp 作为高度
对我来说,我的数据class是
data class Score(
val userId: String,
val username: String,
val avatarPath: String,
val score: Long,
)
我改成了
data class Score(
var userId: String? = null,
var username: String? = null,
var avatarPath: String? = null,
var score: Long? = null,
)
现在可以使用了!!