Just using paging3 library. Want to add search from editText of list in adapter. I can not do search for paging3. I just trying to get list pagingDataLocal variable and trying to filter this in editText onTextChanged but with this I can not use adapter.submitData code because it's not suspend method. How can do search for paging3 with a list that I get from api? Can I do it without not request api for every time when user enter keyword to editText?
BlockContactsBottomSheetDialog.kt
@AndroidEntryPoint
class BlockContactsBottomSheetDialog() : BaseBottomSheetDialog<DialogBottomSheetBlockContactsBinding>() {
private var pagingDataLocal: PagingData<BlockedUserList>? = null
override fun onCreateFinished() {
binding.apply {
editTextChangListener()
viewModel.getPaginationData()
}
}
override fun initObservers() {
lifecycleScope.launch {
viewModel.pagingData.collect { pagingData ->
pagingDataLocal = pagingData
hideProgress()
adapter?.submitData(pagingData)
}
}
adapter?.addLoadStateListener { loadState ->
if ( loadState.append.endOfPaginationReached )
{
if ( adapter?.itemCount!! < 1) {
binding.groupEmptyBottomSheetBlockContacts.visible()
}
else {
binding.groupEmptyBottomSheetBlockContacts.invisible()
}
}
}
private fun editTextChangListener() {
binding.apply {
binding.etSearchBottomSheetBlockContacts.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
val searchText = s.toString().lowercase()
if (searchText.isEmpty()) {
val searchList = pagingDataLocal?.filter { it.fullName?.contains(searchText) == true }
adapter?.submitData(searchList!!)
} else {
}
}
}
}
}
BlockContactsPagingSource.kt
class BlockContactsPagingSource(
private val yourDataSource: BlockedUsersService
) : PagingSource<Int, BlockedUserList>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, BlockedUserList> {
return try {
val data = yourDataSource.getListBlockedUsers(params.key ?: 0, params.loadSize)
LoadResult.Page(
data = data.data.items ?: emptyList(),
prevKey = if (params.key == 0) null else params.key?.minus(1),
nextKey = if (data.data.items.isNullOrEmpty()) null else params.key?.plus(1)
)
} catch (e: IOException) {
LoadResult.Error(e)
} catch (e: HttpException) {
LoadResult.Error(e)
}
}
override fun getRefreshKey(state: PagingState<Int, BlockedUserList>): Int? {
return state.anchorPosition?.let { anchorPosition ->
val anchorPage = state.closestPageToPosition(anchorPosition)
anchorPage?.prevKey?.plus(1) ?: anchorPage?.nextKey?.minus(1)
}
}
}
BlockContactsBottomSheetDialogViewModel.kt
@HiltViewModel
class BlockContactsBottomSheetDialogViewModel @Inject constructor(
private val blockedUsersService: BlockedUsersService
) : ViewModel() {
private val _pagingData = MutableStateFlow<PagingData<BlockedUserList>>(PagingData.empty())
val pagingData: Flow<PagingData<BlockedUserList>> get() = _pagingData
private var pageSize = 20
val pagingConfig = PagingConfig(
pageSize = pageSize,
enablePlaceholders = false
)
fun getPaginationData() {
val pager = Pager(
config = pagingConfig,
pagingSourceFactory = { BlockContactsPagingSource(blockedUsersService) }
)
viewModelScope.launch {
pager.flow.collectLatest { pagingData ->
_pagingData.value = pagingData
}
}
}
}
If there is not filtering query endpoint for Rest API, so you need to filter yourself (maybe using regex) like below:
Attention: list comes from viewModel. pattern comes from editText.