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

Android MVVM架构下两个同布局RecyclerView数据异常求助

解决两个RecyclerView共享/显示数据异常的问题

我来帮你梳理下问题的根源,然后一步步给出可行的解决方案:

问题核心分析

你遇到的问题本质上是数据集共享/覆盖以及LiveData异步处理错误导致的:

  1. 最初用同一个UnsortedAdapter实例给两个RecyclerView,两次调用setData会直接覆盖Adapter内部的数据集,所以两个列表最终都会显示最后一次设置的数据。
  2. 后续尝试的方案中,Repository里用AsyncTask.get()同步获取LiveData的方式是错误的——Room的Dao返回LiveData时会自动在后台执行查询,不需要手动用AsyncTask包裹,这种同步获取会阻塞主线程,导致LiveData无法正确触发生命周期绑定,进而出现数据不显示的问题。

可行解决方案

1. 复用原Adapter,创建两个独立实例

因为两个RecyclerView的布局和绑定逻辑完全一致,只是数据源不同,不需要新建UnsortedAdapter2,只需要创建两个UnsortedAdapter的独立实例即可,每个实例维护自己的数据集。

2. 修正Repository和ViewModel的LiveData逻辑

首先修改UnsortedRepository,去掉错误的AsyncTask包裹:

public class UnsortedRepository {
    private UnsortedDao unsortedDao;
    private LiveData<List<Unsorted>> allUnsorted;

    public UnsortedRepository(Application application){
        UnsortedDatabase database = UnsortedDatabase.getInstance(application);
        unsortedDao = database.unsortedDao();
        allUnsorted = unsortedDao.getAllUnsorted();
    }

    // 直接返回Dao的LiveData,Room会自动在后台执行查询
    public LiveData<List<Unsorted>> getUnsortedWhereDateIs(String currentDate) {
        return unsortedDao.getUnsortedWhereDateIs(currentDate);
    }
}

然后简化UnsortedViewModel的对应方法:

public class UnsortedViewModel extends AndroidViewModel {
    // ... 其他代码不变
    public LiveData<List<Unsorted>> getUnsortedWhereDateIs(String currentDate) {
        return repository.getUnsortedWhereDateIs(currentDate);
    }
    // ... 其他代码不变
}

3. Activity中正确初始化并绑定数据

在Activity中创建两个独立的Adapter,分别绑定到对应的RecyclerView,然后观察LiveData并分别处理数据源:

// 初始化两个独立的Adapter实例
final UnsortedAdapter eatFrogAdapter = new UnsortedAdapter();
final UnsortedAdapter rhythmsAdapter = new UnsortedAdapter();

// 配置第一个RecyclerView
eatFrog.setHasFixedSize(true);
eatFrog.setLayoutManager(new LinearLayoutManager(this));
eatFrog.setAdapter(eatFrogAdapter);

// 配置第二个RecyclerView
biologicalRhythms.setHasFixedSize(true);
biologicalRhythms.setLayoutManager(new LinearLayoutManager(this));
biologicalRhythms.setAdapter(rhythmsAdapter);

// 观察数据源,分别处理并设置给对应Adapter
viewModel.getUnsortedWhereDateIs(currentDate).observe(this, unsortedList -> {
    if (unsortedList == null) return;
    
    // 处理第一个列表的数据
    List<Unsorted> eatFrogData = EatAFrog(unsortedList);
    eatFrogAdapter.setData(eatFrogData);
    eatAFrogList = eatFrogData;

    // 处理第二个列表的数据
    List<Unsorted> rhythmsData = BiologicalRhythms(unsortedList);
    rhythmsAdapter.setData(rhythmsData);
    biologicalList = rhythmsData;
});

4. 优化Adapter的setData方法(可选)

为了避免直接替换列表引用可能带来的问题,可以优化setData方法:

public void setData(List<Unsorted> unsortedList){
    this.list.clear();
    this.list.addAll(unsortedList);
    notifyDataSetChanged();
}

额外MVVM架构优化建议

按照MVVM的职责分离原则,数据处理逻辑应该放在ViewModel中,而不是Activity。可以在ViewModel中提前处理好两个数据集,暴露对应的LiveData给Activity观察:

在ViewModel中添加:

private final MutableLiveData<List<Unsorted>> eatFrogLiveData = new MutableLiveData<>();
private final MutableLiveData<List<Unsorted>> rhythmsLiveData = new MutableLiveData<>();

public LiveData<List<Unsorted>> getEatFrogLiveData() {
    return eatFrogLiveData;
}

public LiveData<List<Unsorted>> getRhythmsLiveData() {
    return rhythmsLiveData;
}

public void loadTasksByDate(String currentDate) {
    repository.getUnsortedWhereDateIs(currentDate).observeForever(unsortedList -> {
        if (unsortedList != null) {
            eatFrogLiveData.setValue(EatAFrog(unsortedList));
            rhythmsLiveData.setValue(BiologicalRhythms(unsortedList));
        }
    });
}

然后Activity中只需要观察对应LiveData:

viewModel.loadTasksByDate(currentDate);

viewModel.getEatFrogLiveData().observe(this, eatFrogData -> {
    eatFrogAdapter.setData(eatFrogData);
    eatAFrogList = eatFrogData;
});

viewModel.getRhythmsLiveData().observe(this, rhythmsData -> {
    rhythmsAdapter.setData(rhythmsData);
    biologicalList = rhythmsData;
});

这样Activity的代码更简洁,ViewModel承担了数据处理的职责,完全符合MVVM的架构设计。

内容的提问来源于stack exchange,提问作者Alisa Petrova

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 13:07:40