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进行调用即可。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐