问题描述
我只显示相册以及分页功能.现在,当有人搜索时,我想使分页无效
I simply display photo gallery along with paging functionality. Now I want to invalidate pagination when someone search
但是每当我在搜索中调用无效时.应用程序崩溃..
But whenever I call invalidate on search. App crashes..
PhotoFragment.kt
@AndroidEntryPoint
class PhotosFragment : BaseFragment<FragmentPhotosBinding,PhotosFragmentViewModel>(R.layout.fragment_photos),
SearchView.OnQueryTextListener, LifecycleObserver {
override val mViewModel: PhotosFragmentViewModel by viewModels()
private lateinit var photoAdapter: PhotoCollectionAdapter
override fun onAttach(context: Context) {
super.onAttach(context)
activity?.lifecycle?.addObserver(this)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setHasOptionsMenu(true)
///mViewModel.setFilter(getString(R.string.search_filter_default_value))
initAdapter()
}
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun onCreated(){
mViewModel.trendingPhotos.observe(viewLifecycleOwner, Observer {
photoAdapter.submitData(lifecycle,it)
})
}
private fun initAdapter() {
photoAdapter = PhotoCollectionAdapter()
photoAdapter.stateRestorationPolicy = RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY
mBinding.recyclerView.apply {
layoutManager = LinearLayoutManager(context)
setHasFixedSize(true)
adapter = photoAdapter
}
photoAdapter.addLoadStateListener { loadState ->
mBinding.recyclerView.isVisible = loadState.refresh is LoadState.NotLoading
val errorState = loadState.source.append as? LoadState.Error
?: loadState.source.prepend as? LoadState.Error
?: loadState.append as? LoadState.Error
?: loadState.prepend as? LoadState.Error
errorState?.let {
}
}
}
var timer: CountDownTimer? = null
override fun onQueryTextSubmit(p0: String?): Boolean = false
override fun onQueryTextChange(newText: String?): Boolean {
timer?.cancel()
timer = object : CountDownTimer(1000, 2500) {
override fun onTick(millisUntilFinished: Long) {}
override fun onFinish() {
Timber.d("query : %s", newText)
if (newText!!.trim().replace(" ", "").length >= 3) {
mViewModel.cachedFilter = newText
mViewModel.setFilter(newText)
}
///afterTextChanged.invoke(editable.toString())
}
}.start()
return true
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.search_menu, menu)
// Get the SearchView and set the searchable configuration
val searchManager = activity?.getSystemService(Context.SEARCH_SERVICE) as SearchManager
//val searchManager = activity!!.getSystemService(Context.SEARCH_SERVICE) as SearchManager
(menu.findItem(R.id.app_bar_search).actionView as SearchView).apply {
// Assumes current activity is the searchable activity
setSearchableInfo(searchManager.getSearchableInfo(activity?.componentName))
setIconifiedByDefault(false) // Do not iconify the widget; expand it by default
queryHint = getString(R.string.search_view_hint)
setQuery(
if (mViewModel.cachedFilter.isEmpty()) getString(R.string.search_filter_default_value) else mViewModel.cachedFilter,
true
)
isSubmitButtonEnabled = true
}.setOnQueryTextListener(this)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return view?.let {
NavigationUI.onNavDestinationSelected(item,it.findNavController())
}?: kotlin.run {
super.onOptionsItemSelected(item)
}
}
}
PhotosFragmentViewModel.kt
@HiltViewModel
class PhotosFragmentViewModel @Inject constructor(
private val photoPagingSourceRx: PhotoPagingSourceRx
): BaseViewModel() {
private val _trendingPhotos = MutableLiveData<PagingData<Models.PhotoResponse>>()
val trendingPhotos: LiveData<PagingData<Models.PhotoResponse>>
get() = _trendingPhotos
var cachedFilter: String = ""
fun setFilter(filter: String) {
photoPagingSourceRx.setFilter(if (cachedFilter.isEmpty()) filter else cachedFilter)
}
init {
viewModelScope.launch {
getPhotosRx().cachedIn(viewModelScope).subscribe {
_trendingPhotos.value = it
}
}
}
private fun getPhotosRx(): Flowable<PagingData<Models.PhotoResponse>> {
return Pager(
config = PagingConfig(
pageSize = 20,
enablePlaceholders = false,
prefetchDistance = 5
),
pagingSourceFactory = { photoPagingSourceRx }
).flowable
}
}
PhotoPagingSourceRx.kt
@Singleton
class PhotoPagingSourceRx @Inject constructor(
private val restApi: RestApi
): RxPagingSource<Int, Models.PhotoResponse>() {
private var filter: String = "Flowers"
private var lastFilter = filter
fun setFilter(filter: String) {
this.filter = filter
}
override fun loadSingle(params: LoadParams<Int>): Single<LoadResult<Int, Models.PhotoResponse>> {
val page = if(lastFilter == filter) params.key ?: 1 else 1
lastFilter = filter
return restApi.getPhotos(filter,20,page).subscribeOn(Schedulers.io()).map {
Log.v("pagingLog","page -> $page ) ")
LoadResult.Page(
data = it.response,
prevKey = if (page == 1) null else page - 1,
nextKey = page + 1
) as LoadResult<Int, Models.PhotoResponse>
}.onErrorReturn {
LoadResult.Error(it)
}
}
override fun getRefreshKey(state: PagingState<Int, Models.PhotoResponse>): Int? {
return state.anchorPosition
}
}
推荐答案
我还没有机会查看您的崩溃,使无效工作绝对重要,因为PagingSource的单个实例旨在表示一个不变的快照.并在更改时失效(因此在此处动态设置过滤器无法正常工作).
I didn't get a chance to look at your crash yet, getting invalidation working is definitely important as a single instance of PagingSource is meant to represent an immutable snapshot and invalidate when it changes (so setting filter dynamically does not work well here).
请改为尝试此方法,因为您似乎需要将过滤器传递给网络api:
Instead try this approach since it looks like you need to pass filter to network api:
ViewModel.kt
ViewModel.kt
val queryFlow = MutableStateFlow<String>("")
val pagingDataFlow = queryFlow.map { query ->
Pager(...) {
PhotoPagingSourceRx(query)
}.flow
.cachedIn(viewModelScope)
}
PhotoPagingSourceRx(顺便说一句,不能是单例)
PhotoPagingSourceRx (btw, this cannot be a singleton)
class PhotoPagingSourceRx @Inject constructor(
private val restApi: RestApi,
private val filter: String,
): RxPagingSource<Int, Models.PhotoResponse>() {
override fun loadSingle(..): Single<LoadResult<Int, Models.PhotoResponse>> { ... }
override fun getRefreshKey(..): Int? { ... }
}
这篇关于不切实际的分页库3.0筛选器/搜索功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!