【问题标题】:MVVM Room -> DAO -> Repository -> ViewModel -> Activity using lists and background threadMVVM Room -> DAO -> Repository -> ViewModel -> Activity 使用列表和后台线程
【发布时间】:2021-04-11 11:03:49
【问题描述】:

我一直在为实现这个而苦苦挣扎,我看过很多教程,但它们总是展示基本示例,似乎从未考虑到这些数据结构和线程。

我确信开发人员每天都会这样做,因此应该很容易有人向我展示。

问题:

我有我的 Room 数据库,假设我有一个数据类型“级别”的列表。我希望能够观察 allLevels 列表。目前的架构是我有一个levelDAO

public interface LevelDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insert(Level... Levels);
    @Update
    void update(Level... Levels);
    @Delete
    void delete(Level... Levels);

    //Live Data
    //Get All Live Levels
    @Query("SELECT * FROM Level")
    MutableLiveData<List<Level>> selectLiveAllLevels();


}

然后我有一个关卡存储库

public class LevelRepository {

    private LevelDao levelDao;
    private MutableLiveData<List<Level>> allLevels;

    public LevelRepository(Application application){
        WayMapDatabase wayMapDatabase = WayMapDatabase.getInstance(application);
        levelDao = wayMapDatabase.levelDao();
        allLevels = levelDao.selectLiveAllLevels();
    }

    public void insert(Level level){
        new InsertLevelAsyncTask(levelDao).execute(level);
    }
    public void update(Level level){
        new UpdateLevelAsyncTask(levelDao).execute(level);
    }
    public void delete(Level level){
        new DeleteLevelAsyncTask(levelDao).execute(level);
    }

    //Live Data
    public MutableLiveData<List<Level>> getLiveAllLevels(){
        return allLevels;
    }

    //Async Tasks
    private static class InsertLevelAsyncTask extends AsyncTask<Level, Void, Void> {

        private LevelDao levelDao;
        private InsertLevelAsyncTask(LevelDao levelDao){
            this.levelDao = levelDao;
        }
        @Override
        protected Void doInBackground(Level... levels) {
            levelDao.insert(levels[0]);
            return null;
        }
    }

    private static class UpdateLevelAsyncTask extends AsyncTask<Level, Void, Void> {

        private LevelDao levelDao;
        private UpdateLevelAsyncTask(LevelDao levelDao){
            this.levelDao = levelDao;
        }
        @Override
        protected Void doInBackground(Level... levels) {
            levelDao.update(levels[0]);
            return null;
        }
    }

    private static class DeleteLevelAsyncTask extends AsyncTask<Level, Void, Void> {

        private LevelDao levelDao;
        private DeleteLevelAsyncTask(LevelDao levelDao){
            this.levelDao = levelDao;
        }
        @Override
        protected Void doInBackground(Level... levels) {
            levelDao.delete(levels[0]);
            return null;
        }
    }

}

正如您所看到的,以下教程向我展示了如何将基本的插入、更新、删除放到后台线程中(我认为)。但是 getLiveLevels() 不是,我认为这永远不会起作用,因为我们必须在后台线程上连接到数据库?

然后我有我的 ViewModel

public class MainViewModel extends AndroidViewModel {

    //Test
    private LevelRepository levelRepository;
    private MutableLiveData<List<Level>> allLevels;
    //Test

    public MainViewModel(@NonNull Application application) {
        super(application);

        //Test
        levelRepository = new LevelRepository(application);
        allLevels = levelRepository.getLiveAllLevels();
        //Test
    }

    public LiveData<List<Level>> getAllLevels(){
        if(allLevels == null){
            allLevels = levelRepository.getLiveAllLevels();
        }
        return allLevels;
    }
}

然后我继续观察我的活动中的 viewModel 对象,但这似乎永远不会工作列表永远不会更新我没有收到错误只是没有更新列表所以它非常令人沮丧。

我在活动中观察如下:

mainViewModel= ViewModelProviders.of(this).get(MainViewModel.class);

        mainViewModel.getAllLevels().observe(this, new Observer<List<Level>>() {
            @Override
            public void onChanged(List<Level> levels) {
                Log.d(TAG, "onChanged:  changed; "+ levels.size());
            }
        });

如果有人向我展示适用于此实现的 DAO、存储库、ViewModel、Activity 实现,那将非常有帮助,这样我就可以在我的其他房间交互中复制它,包括确保它在后台线程和用于 Livedata 列表。

【问题讨论】:

  • 谁能提出一个解决方案,我认为这将是一个非常常见的实现?
  • 设置 Room 需要一些练习,我建议通过一个多月前更新的“Android Room with a View”代码实验室。developer.android.com/codelabs/android-room-with-a-view#0这个代码实验室应该回答你所有的问题.
  • @Shawn 感谢您的提示,但是该示例再次没有处理任何线程,有 cmets 说冲突的事情,例如: // Room 在单独的线程上执行所有查询。和后面的 3 行 // 您必须在非 UI 线程上调用它,否则您的应用程序将抛出异​​常。有没有办法处理 dao 级别的线程,所以我在调用此数据时不必考虑这一点?这些评论是否意味着任何涉及 LiveData 的查询我都不必担心线程?

标签: android mvvm repository-pattern dao android-livedata


【解决方案1】:

使用 Room 时,所有查询都在单独的线程上处理,这是使用 Room 的优势之一。

此屏幕截图取自代码实验室。 https://developer.android.com/codelabs/android-room-with-a-view#8

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-14
    • 2014-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-06
    相关资源
    最近更新 更多