Room与LiveData、ViewModel结合使用(2021.1.3)

直接使用Room的劣势

Android在UI线程不能执行耗时操作,在工作线程不能刷新UI(别在这抬杠,我知道一些情况下可以)而我们的数据更新变化了自然需要给用户展示出来看,但是数据变化又在工作线程,这就涉及到线程间通信,很不方便。虽然我们有Hander,AsyncTask,runOnUiThread等等很多好用的原生支持,甚至还有很多第三方库,但这些目前看来都不是最优解。

解决方案

  • 在以往我们数据发生变化时都需要再去在工作线程中查询一遍数据然后把数据再给到UI线程去刷新,但是现在我们希望数据发生变化时,能自动接收到通知拿到最新数据,怎么搞?LiveData帮我们来搞定,这样当Room数据库中的数据发生变化时,通过LiveData组件通知View层,就可以实现数据的更新了。

  • LiveData通常与ViewModel一起使用,ViewModel是用于存放数据的,因此我们可以将数据库放在ViewModel中进行实例化,但数据库的实例化需要用到Context,而ViewModel中最好不要传入Context,因此直接使用ViewModel不妥,那我们使用它的子类AndroidViewModel,其构造方法中含有Application参数,其作为Context的子类刚好可以用来初始化数据库实例。

案例优化

请先阅读上篇,点击这里

  1. 修改三国人物表的Dao文件,我们希望当数据发生变化时,能够收到一个实时的通知,这里用LiveData将数据进行包装,如下:

    @Dao
    public interface EmperorDao {
        //删除了上篇中的代码
        
        //使用LiveData将结果List<Emperor>包装起来
        @Query("SELECt * FROM emperor_table")
        public LiveData<List<Emperor>> queryEmperorsByLiveData();
    }
    
  2. 创建EmperorViewModel类,在构造器中初始化数据库,并且用LiveData包装List

    public class EmperorViewModel extends AndroidViewModel {
    
        private MyDatabase myDatabase;
        //用LiveData包装List<Emperor>
        private LiveData<List<Emperor>> listEmperor;
    
    
        public EmperorViewModel(@NonNull Application application) {
            super(application);
    
            //初始化数据库实例
            myDatabase = MyDatabase.getDatabaseInstance(application);
            listEmperor = myDatabase.getEmperorDao().queryEmperorsByLiveData();
        }
    
        public LiveData<List<Emperor>> getListEmperor() {
            return listEmperor;
        }
    }
    
  3. 在Activity/Fragment中实例化EmperorViewModel,并监听LiveData中数据的变化

    EmperorViewModel emperorViewModel = new ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication())).get(EmperorViewModel.class);
            emperorViewModel.getListEmperor().observe(this, new Observer<List<Emperor>>() {
                @Override
                public void onChanged(List<Emperor> emperors) {
                    //do what you need
                }
            });
    

结论

运行程序,当数据库每次数据有变动时,onChanged方法会被自动调用,在此方法中刷新数据即可,不需要自己再去开子线程和交换数据了。

上一篇:ViewModel源码分析


下一篇:【面试必会】Android面试相关文章及Github学习资料,全网疯传