在上一节中,简单介绍了Room的基本用法,那么从本节开始,就再介绍Room的其他使用方法。
1、LiveData
在上一节中,通过查询数据库的全部内容,加载到界面上。那么在此Room可以支持LiveData,而且能够感知数据库数据的变化,当数据的数据发生变化时,会实时动态地更新数据到数据库。
@Query("SELECT * FROM STUDENT")
// List getAllStudent();
LiveData<List<Student>> getAllLives();
allLives = studentDao.getAllLives();
allLives.observe(this, new Observer<List<Student>>() {
@Override
public void onChanged(List<Student> students) {
adapter = new ListViewAdapter(getApplicationContext(),students);
lv_main.setAdapter(adapter);
}
});
当执行添加、删除操作时,LiveData会感知数据库的数据变化,从而动态地显示数据。
2、AsyncTask
AsyncTask
是Android中一种异步任务框架,是一个泛型抽象类,常见的就是3参数、5方法,有在后台子线程执行异步任务的doInBackground
,也有在主线程更新UI的onPostExecute
方法…
在上一节中,使用Room时是在主线程做的操作,是因为加了allowMainThreadQueries()
允许在主线程执行查询操作,但是数据库的操作一般是不允许在主线程的,因此就需要用到AsyncTask
。
static class InsertTask extends AsyncTask<Student,Void,Void>{
private StudentDao dao;
public InsertTask(StudentDao dao) {
this.dao = dao;
}
@Override
protected Void doInBackground(Student... students) {
dao.insertStudent(students);
return null;
}
}
通过这样的方式在后台进行DML操作,就可以不写allowMainThreadQueries()
这段代码了。
//插入数据
btn_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Student student = new Student("小王",13);
new InsertTask(studentDao).execute(student);
}
});
3、ViewModel
这样改进之后,Activity端的代码显得非常臃肿,因此可以使用ViewModel,作为中间载体,来作为View层界面请求数据源。
ViewModel之前在MVVM架构中,已经介绍很多了,包括它的生命周期等。
public class StudentViewModel extends AndroidViewModel {
private StudentDataBase dataBase;
private StudentDao dao;
//数据源
private LiveData<List<Student>> getAll;
public StudentViewModel(@NonNull Application application) {
super(application);
dataBase = StudentDataBase.getInstance(application);
dao = dataBase.getDao();
}
//请求插入数据
public void insert(Student... students){
new InsertTask(dao).execute(students);
}
//查询数据
public AsyncTask<String, Void, Integer> getAgeByName(String name){
return new QueryTask(dao).execute(name);
}
public LiveData<List<Student>> getLive(){
if(getAll == null){
getAll = dao.getAllLives();
}
return getAll;
}
static class InsertTask extends AsyncTask<Student,Void,Void> {
private StudentDao dao;
public InsertTask(StudentDao dao) {
this.dao = dao;
}
@Override
protected Void doInBackground(Student... students) {
dao.insertStudent(students);
return null;
}
}
static class QueryTask extends AsyncTask<String, Void, Integer> {
private StudentDao dao;
public QueryTask(StudentDao dao) {
this.dao = dao;
}
@Override
protected Integer doInBackground(String... strings) {
int age = dao.getStudentByName(strings[0]);
return age;
}
}
}
在View层界面,就可以实例化ViewModel使用内部的方法。
viewModel = new ViewModelProvider(this,
new ViewModelProvider.AndroidViewModelFactory(getApplication()))
.get(StudentViewModel.class);
allLives = viewModel.getLive();
allLives.observe(this, new Observer<List<Student>>() {
@Override
public void onChanged(List<Student> students) {
adapter = new ListViewAdapter(getApplicationContext(),students);
lv_main.setAdapter(adapter);
}
});
4、Model层实例Repository
在MVVM架构中,也包括在MVP架构中,有讲过Model的主要职责,除了网络请求之外,还有数据库的查询数据也是在Model层执行。
所以还要抽出一个Model层,在Room中,使用一个仓库类Repository。
public class StudentRepository {
//数据请求
private StudentDataBase dataBase;
private StudentDao dao;
private LiveData<List<Student>> getAll;
public StudentRepository(Context context) {
dataBase = StudentDataBase.getInstance(context.getApplicationContext());;
dao = dataBase.getDao();
}
public LiveData<List<Student>> getGetAll() {
if(getAll == null) {
getAll = dao.getAllLives();
}
return getAll;
}
//插入数据
//请求插入数据
public void insert(Student... students){
new InsertTask(dao).execute(students);
}
static class InsertTask extends AsyncTask<Student,Void,Void> {
private StudentDao dao;
public InsertTask(StudentDao dao) {
this.dao = dao;
}
@Override
protected Void doInBackground(Student... students) {
dao.insertStudent(students);
return null;
}
}
}
再对比一下之前的ViewModel,是不更简洁了一些。
public class StudentViewModel extends AndroidViewModel {
private StudentRepository repository;
//数据源
private LiveData<List<Student>> getAll;
public StudentViewModel(@NonNull Application application) {
super(application);
repository = new StudentRepository(application);
}
//请求插入数据
public void insert(Student... students){
repository.insert(students);
}
public LiveData<List<Student>> getLive(){
getAll = repository.getGetAll();
return getAll;
}
}