Paging 3结合Room实现搜索功能时清空筛选后结果交替显示异常求助
问题根因
你遇到的交替显示数据问题核心是多个Paging订阅同时存活:每次调用loadContactList()时都会新增一个独立的RxJava订阅,旧的搜索对应的订阅没有被取消,当数据库触发更新时,所有存活的订阅都会返回对应搜索条件的Paging数据,先后推送给适配器就会出现交替显示的现象。
另外你cachedIn的使用方式完全无效:PagingRx.cachedIn()会返回一个新的Observable实例,你当前的写法没有接收返回值,等于这行代码没有任何作用。
解决步骤
1. 修正ViewModel订阅逻辑,避免多订阅叠加
每次触发新的搜索前,先销毁上一次搜索的旧订阅,防止多个订阅同时推送数据:
// ViewModel 新增成员变量存储当前Paging订阅 private Disposable pagingDisposable; @Override public void loadContactList(String searchQuery) { Log.e(TAG, "loadContactList: searchQuery "+searchQuery ); // 先销毁旧订阅 if (pagingDisposable != null && !pagingDisposable.isDisposed()) { pagingDisposable.dispose(); } pagingDisposable = mRepository.getContactDataSource().getContactListPaging(ViewModelKt.getViewModelScope(this), searchQuery) .observeOn(Schedulers.io()) .subscribeOn(Schedulers.computation()) .subscribe(contactPagingData -> { contactListLiveDta.postValue(contactPagingData); swipeRefreshLiveData.postValue(ViewState.HIDE); }, error -> { AppLog.tagApp().e(TAG + " onError: "); swipeRefreshLiveData.postValue(ViewState.HIDE); contactListLiveDta.postValue(null); }); mDisposable.add(pagingDisposable); }
2. 修正Repository中cachedIn的用法
接收cachedIn的返回值作为最终返回的Observable,让缓存生效:
@Override public Observable<PagingData<Contact>> getContactListPaging(CoroutineScope viewModelScope, @NonNull String searchQuery) { Log.e(TAG, "getContactListPaging: searchQuery "+searchQuery +" "+searchQuery.isEmpty()); Pager<Integer, Contact> searchContactPager = new Pager<>( new PagingConfig(PAGE_SIZE, PREFETCH, PLACEHOLDER, INIT_SIZE), () -> mDao.getAvailableContactWithSearch("%" + searchQuery + "%")); Observable<PagingData<Contact>> contactListPaging = PagingRx.getObservable(searchContactPager); // 接收cachedIn返回的新Observable再返回 return PagingRx.cachedIn(contactListPaging, viewModelScope); }
3. (可选)更规范的搜索切换实现
使用RxJava的switchMap自动管理旧订阅,相同搜索词不会重复触发请求,代码更简洁易维护:
// ViewModel 新增搜索词主题 private final BehaviorSubject<String> searchQuerySubject = BehaviorSubject.createDefault(""); // ViewModel初始化时调用一次即可 private void initPaging() { mDisposable.add(searchQuerySubject .distinctUntilChanged() // 过滤相同的搜索词,避免重复请求 .switchMap(searchQuery -> mRepository.getContactDataSource().getContactListPaging(ViewModelKt.getViewModelScope(this), searchQuery)) .observeOn(Schedulers.io()) .subscribeOn(Schedulers.computation()) .subscribe(contactPagingData -> { contactListLiveDta.postValue(contactPagingData); swipeRefreshLiveData.postValue(ViewState.HIDE); }, error -> { AppLog.tagApp().e(TAG + " onError: "); swipeRefreshLiveData.postValue(ViewState.HIDE); contactListLiveDta.postValue(null); }) ); } // 外部触发搜索时只需更新搜索词即可 @Override public void loadContactList(String searchQuery) { Log.e(TAG, "loadContactList: searchQuery "+searchQuery ); searchQuerySubject.onNext(searchQuery); }
内容的提问来源于stack exchange,提问作者Đinh Đàm Đình
相关产品推荐
相关产品推荐

