LiveData引入
先前每次进行数据更改都要手动调用刷新界面的方法,而学习过的LiveData可以自动检测数据,在变化时进行相应处理。(返回LiveData的方法系统自动放在副线程自动执行)
LiveData<List<Word>> words;
words = wordDao.getAllWords();
textView = findViewById(R.id.textView2);
words.observe(this, new Observer<List<Word>>() {
@Override
public void onChanged(List<Word> words) {
StringBuilder text = new StringBuilder();
for (Word word : words) {
text.append(word.getId()).append(" ").append(word.getWord()).append("=").append(word.getChinese()).append("\n");
}
textView.setText(text.toString());
}
});
用LiveData检测数据库的所有words,当变化时自动更新界面。
数据库连接单例模式优化
数据库连接的初始化是很耗时的操作,而先前代码每次连接都将创建一个实例,是很浪费资源的,那么将其获取方式改为单例模式将大大优化性能。
@Database(entities = {Word.class}, version = 1, exportSchema = false)
public abstract class WordDataBase extends RoomDatabase {
private static WordDataBase instance;
static synchronized WordDataBase getInstance(Context context) {
if (instance == null) {
instance = Room.databaseBuilder(context.getApplicationContext(), WordDataBase.class, "word_database")
.allowMainThreadQueries()
.build();
}
return instance;
}
public abstract WordDao getWordDao();
}
上述即将生成包装为单例模式,每次用getInstance获取实例。
使用:
wordDataBase = WordDataBase.getInstance(this);
wordDao = wordDataBase.getWordDao();
words = wordDao.getAllWords();
线程操作
数据库操作不应在主线程进行,之前为了简便实现暂时在主线程进行了操作,现在借用AsyncTask进行创建子线程执行操作。
static class UpdateAsync extends AsyncTask<Word, Void, Void> {
private WordDao wordDao;
public UpdateAsync(WordDao wordDao) {
this.wordDao = wordDao;
}
@Override
protected Void doInBackground(Word... words) {
wordDao.updateWords(words);
return null;
}
}
在代码中实现静态内部类进行操作,将所需的Dao由构造方法传入。继承于AsyncTask<Word, Void, Void>
,后面参数代表使用的以及返回值类型。
使用:
update.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Word word = new Word("add", "添加");
word.setId(30);
new UpdateAsync(wordDao).execute(word);
// wordDao.updateWords(word);
}
});
那么此时数据库连接对象就无需设置主线程操作了:
instance = Room.databaseBuilder(context.getApplicationContext(), WordDataBase.class, "word_database")
// .allowMainThreadQueries()
.build();
注:
Async还有几个方法可以重写:
@Override
protected void onPostExecute(Void unused) { //方法执行完成后的操作
super.onPostExecute(unused);
}
@Override
protected void onProgressUpdate(Void... values) { //方法进展过程操作
super.onProgressUpdate(values);
}
@Override
protected void onPreExecute() { //方法执行前操作
super.onPreExecute();
}
数据界面分离
原本数据、代码都写到Acitivity里,而Activity应该只与界面有关,不进行数据存储,所以将系列操作、数据放到ViewModel里存储起来。
public class WordViewModel extends AndroidViewModel {
private WordDao wordDao;
private LiveData<List<Word>> words;
public WordViewModel(@NonNull Application application) {
super(application);
WordDataBase wordDataBase = WordDataBase.getInstance(application);
wordDao = wordDataBase.getWordDao();
words = wordDao.getAllWords();
}
void insertWords(Word ... words) {
new InsertAsync(wordDao).execute(words);
}
void updateWords(Word ... words) {
new UpdateAsync(wordDao).execute(words);
}
void delWords(Word ... words) {
new DelAsync(wordDao).execute(words);
}
void delAllWords() {
new DelAllAsync(wordDao).execute();
}
public LiveData<List<Word>> getWords() {
return words;
}
static class InsertAsync extends AsyncTask<Word, Void, Void> {
private WordDao wordDao;
public InsertAsync(WordDao wordDao) {
this.wordDao = wordDao;
}
@Override
protected Void doInBackground(Word... words) {
wordDao.addWords(words);
return null;
}
}
static class UpdateAsync extends AsyncTask<Word, Void, Void> {
private WordDao wordDao;
public UpdateAsync(WordDao wordDao) {
this.wordDao = wordDao;
}
@Override
protected Void doInBackground(Word... words) {
wordDao.updateWords(words);
return null;
}
}
static class DelAsync extends AsyncTask<Word, Void, Void> {
private WordDao wordDao;
public DelAsync(WordDao wordDao) {
this.wordDao = wordDao;
}
@Override
protected Void doInBackground(Word... words) {
wordDao.deleteWords(words);
return null;
}
}
static class DelAllAsync extends AsyncTask<Void, Void, Void> {
private WordDao wordDao;
public DelAllAsync(WordDao wordDao) {
this.wordDao = wordDao;
}
@Override
protected Void doInBackground(Void... voids) {
wordDao.deleteAllWords();
return null;
}
}
}
将原本的操作、线程任务类放到此处,留出接口供调用即可。
Activity里:
WordViewModel wordViewModel = ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication()).create(WordViewModel.class);
wordViewModel.getWords().observe(this, new Observer<List<Word>>() {
@Override
public void onChanged(List<Word> words) {
StringBuilder text = new StringBuilder();
for (Word word : words) {
text.append(word.getId()).append(" ").append(word.getWord()).append("=").append(word.getChinese()).append("\n");
}
textView.setText(text.toString());
}
});
insert.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
wordViewModel.insertWords(new Word("add", "加"), new Word("delete", "删除"));
// new InsertAsync(wordDao).execute(new Word("add", "加"), new Word("delete", "删除"));
// wordDao.addWords(new Word("add", "加"), new Word("delete", "删除"));
}
});
Activity中只进行方法调用进行操作即可。
仓库Repository类数据中介
对数据库数据的存储、操作创建一个仓库类进行封装管理。
public class WordRepository{
private LiveData<List<Word>> words;
private WordDao wordDao;
public WordRepository(Context context) {
WordDataBase wordDataBase = WordDataBase.getInstance(context.getApplicationContext());
wordDao = wordDataBase.getWordDao();
words = wordDao.getAllWords();
}
void insertWords(Word ... words) {
new InsertAsync(wordDao).execute(words);
}
void updateWords(Word ... words) {
new UpdateAsync(wordDao).execute(words);
}
void delWords(Word ... words) {
new DelAsync(wordDao).execute(words);
}
void delAllWords() {
new DelAllAsync(wordDao).execute();
}
public LiveData<List<Word>> getWords() {
return words;
}
static class InsertAsync extends AsyncTask<Word, Void, Void> {
private WordDao wordDao;
public InsertAsync(WordDao wordDao) {
this.wordDao = wordDao;
}
@Override
protected Void doInBackground(Word... words) {
wordDao.addWords(words);
return null;
}
}
static class UpdateAsync extends AsyncTask<Word, Void, Void> {
private WordDao wordDao;
public UpdateAsync(WordDao wordDao) {
this.wordDao = wordDao;
}
@Override
protected Void doInBackground(Word... words) {
wordDao.updateWords(words);
return null;
}
}
static class DelAsync extends AsyncTask<Word, Void, Void> {
private WordDao wordDao;
public DelAsync(WordDao wordDao) {
this.wordDao = wordDao;
}
@Override
protected Void doInBackground(Word... words) {
wordDao.deleteWords(words);
return null;
}
}
static class DelAllAsync extends AsyncTask<Void, Void, Void> {
private WordDao wordDao;
public DelAllAsync(WordDao wordDao) {
this.wordDao = wordDao;
}
@Override
protected Void doInBackground(Void... voids) {
wordDao.deleteAllWords();
return null;
}
}
}
将和数据有关的内容都放到Repository进行处理。
使用:
public class WordViewModel extends AndroidViewModel {
private WordRepository wordRepository;
public WordViewModel(@NonNull Application application) {
super(application);
wordRepository = new WordRepository(application);
}
public LiveData<List<Word>> getWords() {
return wordRepository.getWords();
}
void insertWords(Word ... words) {
wordRepository.insertWords(words);
}
void updateWords(Word ... words) {
wordRepository.updateWords(words);
}
void delWords(Word ... words) {
wordRepository.delWords(words);
}
void delAllWords() {
wordRepository.delAllWords();
}
}
此时的ViewModel就只用对Repository进行调用即可。