You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 22:15:03