我是靠谱客的博主 神勇吐司,最近开发中收集的这篇文章主要介绍Android学习笔记 93. Room、LiveData 和 ViewModel,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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 创建项目
  1. 创建项目
  2. 更新Gradle配置文件
93.2 创建Word实体

在这里插入图片描述

表结构

在这里插入图片描述

  1. 创建Word类

    public class Word {
       private String mWord;
       public Word(@NonNull String word) {this.mWord = word;}
       public String getWord(){return this.mWord;}
    }
    
  2. 注解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 必须是一个interfaceabstract类。
  • Room 使用 DAO 为您的代码创建干净的 API。
  • 默认情况下,所有查询 ( @Query) 必须在主线程以外的线程上执行。(您稍后再处理。)对于插入或删除等操作,如果您使用提供的便利注释,Room 会为您处理线程管理。
  1. 实现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 和 extend RoomDatabase
  • 通常,整个应用程序只需要一个 Room 数据库实例。
  1. 创建一个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 创建存储库

在这里插入图片描述

  1. 实施存储库

    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

在这里插入图片描述

  1. 实现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布局
  1. 添加样式
  2. 添加布局
  3. 添加回收站视图
  4. 修改FAB图标
93.9 创建一个Adapter并添加RecylerView
  1. 创建 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);
           }
       }
    }
    
  2. 将 RecyclerView 添加到 MainActivity

    RecyclerView recyclerView = findViewById(R.id.recyclerview);
    final WordListAdapter adapter = new WordListAdapter(this);
    recyclerView.setAdapter(adapter);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    
93.10 填充数据库
  1. 创建用于填充数据库的回调

    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与数据连接起来
  1. 显示单词

    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()方法被执行并mWordsWordListAdapter.
  • 可以观察到数据,因为它是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所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(50)

评论列表共有 0 条评论

立即
投稿
返回
顶部