How can make filter the list in recyclerview with using paging3?

35 Views Asked by At

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
            }
        }
    }

}
1

There are 1 best solutions below

1
Zukhriddin Kamolov On
  1. If there is not filtering query endpoint for Rest API, so you need to filter yourself (maybe using regex) like below:

    val list = listOf<BlockedUserList>()
    
    override fun onCreate() {
        val pattern = ".*Mr. *"
    
        val matchingList: List<BlockedUserList> = list.filterByName(pattern)
    }
    
    fun List<BlockedUserList>.filterByName(pattern: String) = this.filter { Regex(pattern).find(it.name).toString().isNotEmpty() }
    
    data class BlockedUserList(val name: String) 
    

Attention: list comes from viewModel. pattern comes from editText.