如何通过点击按钮对Room数据库的LiveData进行排序(MVVM架构)
解决RecyclerView动态切换排序的方案
你的核心问题是当前ViewModel只固定返回按日期排序的LiveData,无法动态切换数据源。下面是基于MVVM+LiveData的修改方案:
1. 定义排序类型枚举
先创建一个枚举类管理排序选项,避免使用魔法值:
public enum SortType { DATE, DISTANCE, DURATION }
2. 修改RunRepository
添加获取不同排序列表的方法,直接返回Dao对应的LiveData:
public class RunRepository { private RunDao mRunDao; RunRepository(Application application) { RunRoomDatabase db = RunRoomDatabase.getDatabase(application); mRunDao = db.runDao(); } // 按日期排序 LiveData<List<Run>> getRunsByDate() { return mRunDao.getRunsByDate(); } // 按距离排序 LiveData<List<Run>> getRunsByDistance() { return mRunDao.getRunsByDistance(); } // 按时长排序 LiveData<List<Run>> getRunsByDuration() { return mRunDao.getRunsByDuration(); } // 原有insert、delete方法保留 void insert(Run run) { RunRoomDatabase.databaseWriteExecutor.execute(() -> mRunDao.insert(run)); } public void delete(Run run) { RunRoomDatabase.databaseWriteExecutor.execute(() -> { mRunDao.deleteRun(run); }); } }
3. 修改RunViewModel(关键改动)
用MutableLiveData维护当前排序类型,通过Transformations.switchMap动态切换数据源:
import androidx.lifecycle.Transformations; public class RunViewModel extends AndroidViewModel { private RunRepository mRepository; private final MutableLiveData<SortType> currentSortType = new MutableLiveData<>(SortType.DATE); // 动态生成的排序后列表LiveData private final LiveData<List<Run>> sortedRuns; public RunViewModel(Application application) { super(application); mRepository = new RunRepository(application); // 监听排序类型变化,自动切换对应数据源 sortedRuns = Transformations.switchMap(currentSortType, sortType -> { switch (sortType) { case DISTANCE: return mRepository.getRunsByDistance(); case DURATION: return mRepository.getRunsByDuration(); case DATE: default: return mRepository.getRunsByDate(); } }); } // 对外暴露动态排序的列表 LiveData<List<Run>> getSortedRuns() { return sortedRuns; } // 提供切换排序类型的方法 public void setSortType(SortType sortType) { currentSortType.setValue(sortType); } // 原有insert、delete方法保留 public void insert(Run run) { mRepository.insert(run); } public void delete(Run run) { mRepository.delete(run); } }
4. 修改MainActivity
替换原有的观察对象,点击按钮时调用ViewModel的排序切换方法:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); RecyclerView recyclerView = findViewById(R.id.recyclerview); final RunListAdapter adapter = new RunListAdapter(new RunListAdapter.RunDiff()); recyclerView.setAdapter(adapter); recyclerView.setLayoutManager(new LinearLayoutManager(this)); mRunViewModel = new ViewModelProvider(this).get(RunViewModel.class); // 观察动态排序后的列表,替换原来的getAllRuns() mRunViewModel.getSortedRuns().observe(this, runs -> { adapter.submitList(runs); }); // 按距离排序按钮点击事件 sortByDistanceButton = findViewById(R.id.sortByDistance); sortByDistanceButton.setOnClickListener(view -> { mRunViewModel.setSortType(SortType.DISTANCE); }); // 按时长排序按钮示例 sortByDurationButton = findViewById(R.id.sortByDuration); sortByDurationButton.setOnClickListener(view -> { mRunViewModel.setSortType(SortType.DURATION); }); // 按日期排序按钮(恢复初始排序) sortByDateButton = findViewById(R.id.sortByDate); sortByDateButton.setOnClickListener(view -> { mRunViewModel.setSortType(SortType.DATE); }); }
为什么之前的方法无效?
你之前尝试传递"choice"参数但没效果,大概率是因为没有用switchMap动态绑定排序类型和数据源。原来的实现中,ViewModel返回的是固定的LiveData实例,切换排序参数后不会触发新的数据源订阅;而switchMap会在排序类型变化时自动切换到对应的LiveData,从而触发UI更新。
内容的提问来源于stack exchange,提问作者Apelli
相关产品推荐
相关产品推荐

