概述
Android学习笔记
Android 开发者基础知识 (Java) —— Google Developers 培训团队
文章目录
- Android学习笔记
- Android 开发者基础知识 (Java) —— Google Developers 培训团队
- 第3单元 在后台运行
- 第10课 使用Room存储数据
- 93. Room、LiveData 和 ViewModel
- 93.1 创建项目
- 93.2 创建Word实体
- 93.3 创建DAO
- 93.4 使用LiveData
- 93.5 添加Room数据库
- 93.6 创建存储库
- 93.7 创建ViewModel
- 93.8 为UI添加XML布局
- 93.9 创建一个Adapter并添加RecylerView
- 93.10 填充数据库
- 93.11 将UI与数据连接起来
- 93.12 创建一个用于添加单词的Activity
- 93.13 小结
第3单元 在后台运行
第10课 使用Room存储数据
93. Room、LiveData 和 ViewModel
项目地址:https://github.com/google-developer-training/android-fundamentals-apps-v2/tree/master/RoomWordsSample
93.1 创建项目
- 创建项目
- 更新Gradle配置文件
93.2 创建Word实体
表结构
-
创建Word类
public class Word { private String mWord; public Word(@NonNull String word) {this.mWord = word;} public String getWord(){return this.mWord;} }
-
注解Word类
@Entity(tableName = "word_table") public class Word { @PrimaryKey @NonNull @ColumnInfo(name = "word") private String mWord; public Word(@NonNull String word) {this.mWord = word;} public String getWord(){return this.mWord;} }
93.3 创建DAO
数据访问对象或 Dao
是一个带注释的类,您可以在其中指定 SQL 查询并将它们与方法调用相关联。编译器检查 SQL 是否有错误,然后从注释中生成查询。对于常见查询,库提供了方便的注释,例如@Insert
.
注意:
- DAO 必须是一个
interface
或abstract
类。 - Room 使用 DAO 为您的代码创建干净的 API。
- 默认情况下,所有查询 (
@Query
) 必须在主线程以外的线程上执行。(您稍后再处理。)对于插入或删除等操作,如果您使用提供的便利注释,Room 会为您处理线程管理。
-
实现DAO类
@Dao public interface WordDao { @Insert void insert(Word word); @Query("DELETE FROM word_table") void deleteAll(); @Query("SELECT * from word_table ORDER BY word ASC") List<Word> getAllWords(); }
93.4 使用LiveData
在WordDao中返回LiveData
@Query("SELECT * from word_table ORDER BY word ASC")
LiveData<List<Word>> getAllWords();
93.5 添加Room数据库
Room 是 SQLite 数据库之上的数据库层。Room 负责处理您过去使用数据库助手类(例如 SQLiteOpenHelper
.
- Room 使用 DAO 向其数据库发出查询。
- 默认情况下,为了避免糟糕的 UI 性能,Room 不允许您在主线程上发出数据库查询。
LiveData
需要时,通过在后台线程上自动异步运行查询来应用此规则。 - Room 提供 SQLite 语句的编译时检查。
- 您的
Room
类必须是 abstract 和 extendRoomDatabase
。 - 通常,整个应用程序只需要一个 Room 数据库实例。
-
创建一个Room数据库
@Database(entities = {Word.class}, version = 1, exportSchema = false) public abstract class WordRoomDatabase extends RoomDatabase { public abstract WordDao wordDao(); private static WordRoomDatabase INSTANCE; static WordRoomDatabase getDatabase(final Context context) { if (INSTANCE == null) { synchronized (WordRoomDatabase.class) { if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), WordRoomDatabase.class, "word_database") // Wipes and rebuilds instead of migrating // if no Migration object. // Migration is not part of this practical. .fallbackToDestructiveMigration() .build(); } } } return INSTANCE; } }
93.6 创建存储库
-
实施存储库
public class WordRepository { private WordDao mWordDao; private LiveData<List<Word>> mAllWords; WordRepository(Application application) { WordRoomDatabase db = WordRoomDatabase.getDatabase(application); mWordDao = db.wordDao(); mAllWords = mWordDao.getAllWords(); } LiveData<List<Word>> getAllWords() { return mAllWords; } public void insert (Word word) { new insertAsyncTask(mWordDao).execute(word); } private static class insertAsyncTask extends AsyncTask<Word, Void, Void> { private WordDao mAsyncTaskDao; insertAsyncTask(WordDao dao) { mAsyncTaskDao = dao; } @Override protected Void doInBackground(final Word... params) { mAsyncTaskDao.insert(params[0]); return null; } } }
93.7 创建ViewModel
-
实现WordViewModel
public class WordViewModel extends AndroidViewModel { private WordRepository mRepository; private LiveData<List<Word>> mAllWords; public WordViewModel (Application application) { super(application); mRepository = new WordRepository(application); mAllWords = mRepository.getAllWords(); } LiveData<List<Word>> getAllWords() { return mAllWords; } public void insert(Word word) { mRepository.insert(word); } }
93.8 为UI添加XML布局
- 添加样式
- 添加布局
- 添加回收站视图
- 修改FAB图标
93.9 创建一个Adapter并添加RecylerView
-
创建 WordListAdapter 类
public class WordListAdapter extends RecyclerView.Adapter<WordListAdapter.WordViewHolder> { private final LayoutInflater mInflater; private List<Word> mWords; // Cached copy of words WordListAdapter(Context context) { mInflater = LayoutInflater.from(context); } @Override public WordViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View itemView = mInflater.inflate(R.layout.recyclerview_item, parent, false); return new WordViewHolder(itemView); } @Override public void onBindViewHolder(WordViewHolder holder, int position) { if (mWords != null) { Word current = mWords.get(position); holder.wordItemView.setText(current.getWord()); } else { // Covers the case of data not being ready yet. holder.wordItemView.setText("No Word"); } } void setWords(List<Word> words){ mWords = words; notifyDataSetChanged(); } // getItemCount() is called many times, and when it is first called, // mWords has not been updated (means initially, it's null, and we can't return null). @Override public int getItemCount() { if (mWords != null) return mWords.size(); else return 0; } class WordViewHolder extends RecyclerView.ViewHolder { private final TextView wordItemView; private WordViewHolder(View itemView) { super(itemView); wordItemView = itemView.findViewById(R.id.textView); } } }
-
将 RecyclerView 添加到 MainActivity
RecyclerView recyclerView = findViewById(R.id.recyclerview); final WordListAdapter adapter = new WordListAdapter(this); recyclerView.setAdapter(adapter); recyclerView.setLayoutManager(new LinearLayoutManager(this));
93.10 填充数据库
-
创建用于填充数据库的回调
private static class PopulateDbAsync extends AsyncTask<Void, Void, Void> { private final WordDao mDao; String[] words = {"dolphin", "crocodile", "cobra"}; PopulateDbAsync(WordRoomDatabase db) { mDao = db.wordDao(); } @Override protected Void doInBackground(final Void... params) { // Start the app with a clean database every time. // Not needed if you only populate the database // when it is first created mDao.deleteAll(); for (int i = 0; i <= words.length - 1; i++) { Word word = new Word(words[i]); mDao.insert(word); } return null; } }
93.11 将UI与数据连接起来
-
显示单词
mWordViewModel.getAllWords().observe(this, new Observer<List<Word>>() { @Override public void onChanged(@Nullable final List<Word> words) { // Update the cached copy of the words in the adapter. adapter.setWords(words); } });
93.12 创建一个用于添加单词的Activity
public class NewWordActivity extends AppCompatActivity {
public static final String EXTRA_REPLY =
"com.example.android.roomwordssample.REPLY";
private EditText mEditWordView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_word);
mEditWordView = findViewById(R.id.edit_word);
final Button button = findViewById(R.id.button_save);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent replyIntent = new Intent();
if (TextUtils.isEmpty(mEditWordView.getText())) {
setResult(RESULT_CANCELED, replyIntent);
} else {
String word = mEditWordView.getText().toString();
replyIntent.putExtra(EXTRA_REPLY, word);
setResult(RESULT_OK, replyIntent);
}
finish();
}
});
}
}
将单词插入数据库的代码
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == NEW_WORD_ACTIVITY_REQUEST_CODE && resultCode == RESULT_OK) {
Word word = new Word(data.getStringExtra(NewWordActivity.EXTRA_REPLY));
mWordViewModel.insert(word);
} else {
Toast.makeText(
getApplicationContext(),
R.string.empty_not_saved,
Toast.LENGTH_LONG).show();
}
}
93.13 小结
MainActivity
您有一个应用程序可以在列表 ( ,RecyclerView
,WordListAdapter
)中显示单词。- 您可以将单词添加到列表 (
NewWordActivity
)。 - 一个词是
Word
实体类的一个实例。 - 单词被缓存在
RecyclerViewAdapter
单词List
(mWords
) 中。当数据发生变化时,列表会自动更新并重新显示。 - 发生自动更新是因为在 中
MainActivity
,有一个Observer
观察单词并在单词更改时收到通知。当有变化时,观察者的onChange()
方法被执行并mWords
在WordListAdapter
. - 可以观察到数据,因为它是
LiveData
。观察到的是对象LiveData<List<Word>>
返回的WordViewModel
。 WordViewModel
从用户界面隐藏有关后端的所有内容。它提供了访问 UI 数据的方法,并返回LiveData
以便MainActivity
可以设置观察者关系。视图、活动和片段仅通过ViewModel
. 因此,数据来自哪里并不重要。- 在这种情况下,数据来自存储库。
ViewModel
不需要知道存储库与什么交互。它只需要知道如何与Repository 交互,就是通过Repository 暴露的方法。 - 存储库管理一个或多个数据源。在 RoomWordsSample 应用程序中,该后端是 Room 数据库。Room 是一个包装器并实现了一个 SQLite 数据库。Room 为您做了很多以前必须自己做的工作。例如,Room 可以完成您过去使用
SQLiteOpenHelper
类所做的所有事情。 - DAO 将方法调用映射到数据库查询,因此当 Repository 调用诸如 之类的方法时
getAllWords()
,Room 可以执行**。**SELECT * from word_table ORDER BY word ASC - 观察查询返回的结果
LiveData
。因此,每次 Room 中的数据发生变化时,都会执行Observer
接口的onChanged()
方法并更新 UI。
最后
以上就是神勇吐司为你收集整理的Android学习笔记 93. Room、LiveData 和 ViewModel的全部内容,希望文章能够帮你解决Android学习笔记 93. Room、LiveData 和 ViewModel所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复