实施房间数据库 (Android)
Implementing the Room Database (Android)
我想知道如何在 Android 应用程序中正确集成 Room Library。我看到的一些文章使用单例方法,使用 Respository 进行数据库调用,而其他文章则使用某种形式的依赖注入(Dagger 2)。我想知道这个库的正确集成?
谢谢
咨询official documentation怎么样。
我认为最好的地方是代码实验室,它有一个 simple implementation, as well as a more complex。全部使用 Room。
编辑:以上链接似乎已删除。这里有一些资源可以替代它:
房间基本知识
Room 库充当底层 SQLite 数据库的抽象层。因此,使用房间注释:
- 到数据库和实体,其中实体是代表 table 结构的 POJO classes。
- 指定检索、更新和删除操作。
- 添加约束,例如外键。
- 支持 LiveData。
Room 中有 3 个主要组件
- 实体:用@Entity 注释注释的 class 映射到数据库中的 table。每个实体都保存在自己的 table 中,class 中的每个字段都代表列名。
tableName属性用于定义table的名称
每个实体 class 必须有 at-least 一个主键字段,用 @PrimaryKey 注释
实体 class 中的字段可以使用 @ColumnInfo(name = “name_of_column”) 注释进行注释,以给出特定的列名称
- DAO:数据访问对象可以是一个接口,也可以是一个抽象的 class,带有 @Doa 注释,包含定义要对数据执行的操作的所有方法。这些方法可以用
注释
@Query to retrieve data from database
@Insert to insert data into database
@Delete to delete data from database
@Update to update data in database
- 数据库:数据库是 table 的容器。使用@Database 注释进行注释的抽象 class 用于创建具有给定名称和数据库版本的数据库。
添加这些依赖项:
dependencies {
// Room dependencies
compile 'android.arch.persistence.room:runtime:1.0.0'
annotationProcessor 'android.arch.persistence.room:compiler:1.0.0'
}
创建实体
在创建数据库之前,让我们创建一个实体,命名为 Note,稍后,这个 class 的对象将被添加到数据库中。
@Entity
public class Note {
@PrimaryKey(autoGenerate = true)
private int note_id;
@ColumnInfo(name = "note_content") // column name will be "note_content" instead of "content" in table
private String content;
private String title;
private
public Note(int note_id, String content, String title) {
this.note_id = note_id;
this.content = content;
this.title = title;
}
public int getNote_id() {
return note_id;
}
public void setNote_id(int note_id) {
this.note_id = note_id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Note)) return false;
Note note = (Note) o;
if (note_id != note.note_id) return false;
return title != null ? title.equals(note.title) : note.title == null;
}
@Override
public int hashCode() {
int result = note_id;
result = 31 * result + (title != null ? title.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "Note{" +
"note_id=" + note_id +
", content='" + content + '\'' +
", title='" + title + '\'' +
'}';
}}
创建 DAO
DAO 定义了访问数据库的所有方法,并使用@Dao 注释进行注释。 DAO 充当对数据库中的数据执行 CRUD 操作的合同。
@Dao
public interface NoteDao {
@Query("SELECT * FROM user "+ Constants.TABLE_NAME_NOTE)
List<Note> getAll();
/*
* Insert the object in database
* @param note, object to be inserted
*/
@Insert
void insert(Note note);
/*
* update the object in database
* @param note, object to be updated
*/
@Update
void update(Note repos);
/*
* delete the object from database
* @param note, object to be deleted
*/
@Delete
void delete(Note note);
/*
* delete list of objects from database
* @param note, array of objects to be deleted
*/
@Delete
void delete(Note... note); // Note... is varargs, here note is an array
}
创建数据库
现在,我们已经 table 定义为通过 NoteDao 定义的实体和 CRUD 方法。数据库难题的最后一块是数据库本身。
@Database(entities = { Note.class }, version = 1)
public abstract class NoteDatabase extends RoomDatabase {
public abstract NoteDao getNoteDao();
private static NoteDatabase noteDB;
public static NoteDatabase getInstance(Context context) {
if (null == noteDB) {
noteDB = buildDatabaseInstance(context);
}
return noteDB;
}
private static NoteDatabase buildDatabaseInstance(Context context) {
return Room.databaseBuilder(context,
NoteDatabase.class,
Constants.DB_NAME)
.allowMainThreadQueries().build();
}
public void cleanUp(){
noteDB = null;
}
}
实施数据库交互
下面的代码片段将演示如何使用 Room 数据库插入、更新和删除功能。
public class AddNoteActivity extends AppCompatActivity {
private TextInputEditText et_title,et_content;
private NoteDatabase noteDatabase;
private Note note;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_note);
et_title = findViewById(R.id.et_title);
et_content = findViewById(R.id.et_content);
noteDatabase = NoteDatabase.getInstance(AddNoteActivity.this);
Button button = findViewById(R.id.but_save);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// fetch data and create note object
note = new Note(et_content.getText().toString(),
et_title.getText().toString());
// create worker thread to insert data into database
new InsertTask(AddNoteActivity.this,note).execute();
}
});
}
private void setResult(Note note, int flag){
setResult(flag,new Intent().putExtra("note",note));
finish();
}
private static class InsertTask extends AsyncTask<Void,Void,Boolean> {
private WeakReference<AddNoteActivity> activityReference;
private Note note;
// only retain a weak reference to the activity
InsertTask(AddNoteActivity context, Note note) {
activityReference = new WeakReference<>(context);
this.note = note;
}
// doInBackground methods runs on a worker thread
@Override
protected Boolean doInBackground(Void... objs) {
activityReference.get().noteDatabase.getNoteDao().insertNote(note);
return true;
}
// onPostExecute runs on main thread
@Override
protected void onPostExecute(Boolean bool) {
if (bool){
activityReference.get().setResult(note,1);
}
}
}
}
检索并显示笔记列表
public class NoteListActivity extends AppCompatActivity implements NotesAdapter.OnNoteItemClick{
private TextView textViewMsg;
private RecyclerView recyclerView;
private NoteDatabase noteDatabase;
private List<Note> notes;
private NotesAdapter notesAdapter;
private int pos;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeVies();
displayList();
}
private void displayList(){
// initialize database instance
noteDatabase = NoteDatabase.getInstance(NoteListActivity.this);
// fetch list of notes in background thread
new RetrieveTask(this).execute();
}
private static class RetrieveTask extends AsyncTask<Void,Void,List<Note>>{
private WeakReference<NoteListActivity> activityReference;
// only retain a weak reference to the activity
RetrieveTask(NoteListActivity context) {
activityReference = new WeakReference<>(context);
}
@Override
protected List<Note> doInBackground(Void... voids) {
if (activityReference.get()!=null)
return activityReference.get().noteDatabase.getNoteDao().getNotes();
else
return null;
}
@Override
protected void onPostExecute(List<Note> notes) {
if (notes!=null && notes.size()>0 ){
activityReference.get().notes = notes;
// hides empty text view
activityReference.get().textViewMsg.setVisibility(View.GONE);
// create and set the adapter on RecyclerView instance to display list
activityReference.get().notesAdapter = new NotesAdapter(notes,activityReference.get());
activityReference.get().recyclerView.setAdapter(activityReference.get().notesAdapter);
}
}
}
private void initializeVies(){
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
textViewMsg = (TextView) findViewById(R.id.tv\_\_empty);
// Action button to add note
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(listener);
recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(NoteListActivity.this));
}
}
更新说明
public class AddNoteActivity extends AppCompatActivity {
private TextInputEditText et_title,et_content;
private NoteDatabase noteDatabase;
private Note note;
private boolean update;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_note);
et_title = findViewById(R.id.et_title);
et_content = findViewById(R.id.et_content);
noteDatabase = NoteDatabase.getInstance(AddNoteActivity.this);
Button button = findViewById(R.id.but_save);
if ( (note = (Note) getIntent().getSerializableExtra("note"))!=null ){
getSupportActionBar().setTitle("Update Note");
update = true;
button.setText("Update");
et_title.setText(note.getTitle());
et_content.setText(note.getContent());
}
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
note.setContent(et_content.getText().toString());
note.setTitle(et_title.getText().toString());
noteDatabase.getNoteDao().updateNote(note);
}
});
}
}
删除备注
noteDatabase.getNoteDao().deleteNote(notes.get(pos));
adapterObj.notifyDataSetChanged();
ROOM 数据库
- Room 是 Android 开发中的 SQLite 数据库的 ORM(对象关系映射器),也是 Android Jetpack 的一部分。
- 在 SQLite 数据库
上提供抽象层
- 减少了样板代码的数量
- SQL 查询的编译时验证
ROOM 数据库组件
- 它有 3 个主要组件 Entity、Database、DAO。
- Entity 是用@Entity 注释的数据 class 就像在 SQLite 中创建一个 table 并且模型中的变量 class 就像 table.
中的列
- Database 是一个抽象 class,它扩展了 RoomDatabase 并具有与数据库关联的实体列表。
- DAO(数据访问对象) 是一个定义要在我们的数据库中执行的操作的接口。
ROOM 数据库实现
第 1 步创建 实体 数据 class
@Entity(tableName = "yourOwnTableName")
数据class本地数据(
val column1: String?,
val column2: String?,
@PrimaryKey(autoGenerate = true) val product_local_id: Int?= null
)
第 2 步创建 数据库
@Database(entities = [LocalData::class], version = 1, exportSchema = false)
@TypeConverters
抽象class LocalDB : RoomDatabase() {
abstract fun localDataDao() : LocalDataDAO
companion object{
private var instance : LocalDB ? = null
fun getInstance(context: Context) : LocalDB ?{
if(instance == null){
synchronized(LocalDB ::class){
instance = Room.databaseBuilder(context.applicationContext, LocalDB::class.java, "localBD.db").allowMainThreadQueries().build()
}
}
return instance
}
fun destroyInstance(){
instance = null
}
}
}
第 3 步创建 DAO
@道
接口 LocalDAO {
@Insert
fun insertData(productEntity: LocalData) : Long
@Delete
fun deleteData(productEntity: LocalData) : Int
@Query("Select * from yourOwnTableName")
fun showAllProducts(): List<LocalData>
@Query("SELECT COUNT(*) FROM yourOwnTableName")
fun totalProducts(): Long
}
第 4 步是可选的,正在创建 存储库
class ProductRepository(上下文:上下文){
var dbms : LocalDAO = LocalDB.getInstance(context)?.localDataDao()!!
fun insertData(productEntity: LocalData) : Long{
return dbms.insertData(productEntity)
}
fun deleteData(productEntity: LocalData) : Int{
return dbms.deleteData(productEntity)
}
fun getAllData() : List<LocalData> {
return dbms.showAllProducts()
}
fun checkProductExist(id : Int) : Boolean{
return dbms.exists(id)
}
fun totalProductsInCart() : Long{
return dbms.totalProducts()
}
}
我想知道如何在 Android 应用程序中正确集成 Room Library。我看到的一些文章使用单例方法,使用 Respository 进行数据库调用,而其他文章则使用某种形式的依赖注入(Dagger 2)。我想知道这个库的正确集成?
谢谢
咨询official documentation怎么样。
我认为最好的地方是代码实验室,它有一个 simple implementation, as well as a more complex。全部使用 Room。
编辑:以上链接似乎已删除。这里有一些资源可以替代它:
房间基本知识
Room 库充当底层 SQLite 数据库的抽象层。因此,使用房间注释:
- 到数据库和实体,其中实体是代表 table 结构的 POJO classes。
- 指定检索、更新和删除操作。
- 添加约束,例如外键。
- 支持 LiveData。
Room 中有 3 个主要组件
- 实体:用@Entity 注释注释的 class 映射到数据库中的 table。每个实体都保存在自己的 table 中,class 中的每个字段都代表列名。
tableName属性用于定义table的名称 每个实体 class 必须有 at-least 一个主键字段,用 @PrimaryKey 注释 实体 class 中的字段可以使用 @ColumnInfo(name = “name_of_column”) 注释进行注释,以给出特定的列名称
- DAO:数据访问对象可以是一个接口,也可以是一个抽象的 class,带有 @Doa 注释,包含定义要对数据执行的操作的所有方法。这些方法可以用 注释
@Query to retrieve data from database
@Insert to insert data into database
@Delete to delete data from database
@Update to update data in database
- 数据库:数据库是 table 的容器。使用@Database 注释进行注释的抽象 class 用于创建具有给定名称和数据库版本的数据库。
添加这些依赖项:
dependencies {
// Room dependencies
compile 'android.arch.persistence.room:runtime:1.0.0'
annotationProcessor 'android.arch.persistence.room:compiler:1.0.0'
}
创建实体
在创建数据库之前,让我们创建一个实体,命名为 Note,稍后,这个 class 的对象将被添加到数据库中。
@Entity
public class Note {
@PrimaryKey(autoGenerate = true)
private int note_id;
@ColumnInfo(name = "note_content") // column name will be "note_content" instead of "content" in table
private String content;
private String title;
private
public Note(int note_id, String content, String title) {
this.note_id = note_id;
this.content = content;
this.title = title;
}
public int getNote_id() {
return note_id;
}
public void setNote_id(int note_id) {
this.note_id = note_id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Note)) return false;
Note note = (Note) o;
if (note_id != note.note_id) return false;
return title != null ? title.equals(note.title) : note.title == null;
}
@Override
public int hashCode() {
int result = note_id;
result = 31 * result + (title != null ? title.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "Note{" +
"note_id=" + note_id +
", content='" + content + '\'' +
", title='" + title + '\'' +
'}';
}}
创建 DAO
DAO 定义了访问数据库的所有方法,并使用@Dao 注释进行注释。 DAO 充当对数据库中的数据执行 CRUD 操作的合同。
@Dao
public interface NoteDao {
@Query("SELECT * FROM user "+ Constants.TABLE_NAME_NOTE)
List<Note> getAll();
/*
* Insert the object in database
* @param note, object to be inserted
*/
@Insert
void insert(Note note);
/*
* update the object in database
* @param note, object to be updated
*/
@Update
void update(Note repos);
/*
* delete the object from database
* @param note, object to be deleted
*/
@Delete
void delete(Note note);
/*
* delete list of objects from database
* @param note, array of objects to be deleted
*/
@Delete
void delete(Note... note); // Note... is varargs, here note is an array
}
创建数据库
现在,我们已经 table 定义为通过 NoteDao 定义的实体和 CRUD 方法。数据库难题的最后一块是数据库本身。
@Database(entities = { Note.class }, version = 1)
public abstract class NoteDatabase extends RoomDatabase {
public abstract NoteDao getNoteDao();
private static NoteDatabase noteDB;
public static NoteDatabase getInstance(Context context) {
if (null == noteDB) {
noteDB = buildDatabaseInstance(context);
}
return noteDB;
}
private static NoteDatabase buildDatabaseInstance(Context context) {
return Room.databaseBuilder(context,
NoteDatabase.class,
Constants.DB_NAME)
.allowMainThreadQueries().build();
}
public void cleanUp(){
noteDB = null;
}
}
实施数据库交互
下面的代码片段将演示如何使用 Room 数据库插入、更新和删除功能。
public class AddNoteActivity extends AppCompatActivity {
private TextInputEditText et_title,et_content;
private NoteDatabase noteDatabase;
private Note note;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_note);
et_title = findViewById(R.id.et_title);
et_content = findViewById(R.id.et_content);
noteDatabase = NoteDatabase.getInstance(AddNoteActivity.this);
Button button = findViewById(R.id.but_save);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// fetch data and create note object
note = new Note(et_content.getText().toString(),
et_title.getText().toString());
// create worker thread to insert data into database
new InsertTask(AddNoteActivity.this,note).execute();
}
});
}
private void setResult(Note note, int flag){
setResult(flag,new Intent().putExtra("note",note));
finish();
}
private static class InsertTask extends AsyncTask<Void,Void,Boolean> {
private WeakReference<AddNoteActivity> activityReference;
private Note note;
// only retain a weak reference to the activity
InsertTask(AddNoteActivity context, Note note) {
activityReference = new WeakReference<>(context);
this.note = note;
}
// doInBackground methods runs on a worker thread
@Override
protected Boolean doInBackground(Void... objs) {
activityReference.get().noteDatabase.getNoteDao().insertNote(note);
return true;
}
// onPostExecute runs on main thread
@Override
protected void onPostExecute(Boolean bool) {
if (bool){
activityReference.get().setResult(note,1);
}
}
}
}
检索并显示笔记列表
public class NoteListActivity extends AppCompatActivity implements NotesAdapter.OnNoteItemClick{
private TextView textViewMsg;
private RecyclerView recyclerView;
private NoteDatabase noteDatabase;
private List<Note> notes;
private NotesAdapter notesAdapter;
private int pos;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeVies();
displayList();
}
private void displayList(){
// initialize database instance
noteDatabase = NoteDatabase.getInstance(NoteListActivity.this);
// fetch list of notes in background thread
new RetrieveTask(this).execute();
}
private static class RetrieveTask extends AsyncTask<Void,Void,List<Note>>{
private WeakReference<NoteListActivity> activityReference;
// only retain a weak reference to the activity
RetrieveTask(NoteListActivity context) {
activityReference = new WeakReference<>(context);
}
@Override
protected List<Note> doInBackground(Void... voids) {
if (activityReference.get()!=null)
return activityReference.get().noteDatabase.getNoteDao().getNotes();
else
return null;
}
@Override
protected void onPostExecute(List<Note> notes) {
if (notes!=null && notes.size()>0 ){
activityReference.get().notes = notes;
// hides empty text view
activityReference.get().textViewMsg.setVisibility(View.GONE);
// create and set the adapter on RecyclerView instance to display list
activityReference.get().notesAdapter = new NotesAdapter(notes,activityReference.get());
activityReference.get().recyclerView.setAdapter(activityReference.get().notesAdapter);
}
}
}
private void initializeVies(){
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
textViewMsg = (TextView) findViewById(R.id.tv\_\_empty);
// Action button to add note
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(listener);
recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(NoteListActivity.this));
}
}
更新说明
public class AddNoteActivity extends AppCompatActivity {
private TextInputEditText et_title,et_content;
private NoteDatabase noteDatabase;
private Note note;
private boolean update;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_note);
et_title = findViewById(R.id.et_title);
et_content = findViewById(R.id.et_content);
noteDatabase = NoteDatabase.getInstance(AddNoteActivity.this);
Button button = findViewById(R.id.but_save);
if ( (note = (Note) getIntent().getSerializableExtra("note"))!=null ){
getSupportActionBar().setTitle("Update Note");
update = true;
button.setText("Update");
et_title.setText(note.getTitle());
et_content.setText(note.getContent());
}
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
note.setContent(et_content.getText().toString());
note.setTitle(et_title.getText().toString());
noteDatabase.getNoteDao().updateNote(note);
}
});
}
}
删除备注
noteDatabase.getNoteDao().deleteNote(notes.get(pos));
adapterObj.notifyDataSetChanged();
ROOM 数据库
- Room 是 Android 开发中的 SQLite 数据库的 ORM(对象关系映射器),也是 Android Jetpack 的一部分。
- 在 SQLite 数据库 上提供抽象层
- 减少了样板代码的数量
- SQL 查询的编译时验证
ROOM 数据库组件
- 它有 3 个主要组件 Entity、Database、DAO。
- Entity 是用@Entity 注释的数据 class 就像在 SQLite 中创建一个 table 并且模型中的变量 class 就像 table. 中的列
- Database 是一个抽象 class,它扩展了 RoomDatabase 并具有与数据库关联的实体列表。
- DAO(数据访问对象) 是一个定义要在我们的数据库中执行的操作的接口。
ROOM 数据库实现
第 1 步创建 实体 数据 class
@Entity(tableName = "yourOwnTableName")
数据class本地数据(
val column1: String?, val column2: String?, @PrimaryKey(autoGenerate = true) val product_local_id: Int?= null
)
第 2 步创建 数据库
@Database(entities = [LocalData::class], version = 1, exportSchema = false) @TypeConverters
抽象class LocalDB : RoomDatabase() {
abstract fun localDataDao() : LocalDataDAO companion object{ private var instance : LocalDB ? = null fun getInstance(context: Context) : LocalDB ?{ if(instance == null){ synchronized(LocalDB ::class){ instance = Room.databaseBuilder(context.applicationContext, LocalDB::class.java, "localBD.db").allowMainThreadQueries().build() } } return instance } fun destroyInstance(){ instance = null } }
}
第 3 步创建 DAO
@道 接口 LocalDAO {
@Insert fun insertData(productEntity: LocalData) : Long @Delete fun deleteData(productEntity: LocalData) : Int @Query("Select * from yourOwnTableName") fun showAllProducts(): List<LocalData> @Query("SELECT COUNT(*) FROM yourOwnTableName") fun totalProducts(): Long
}
第 4 步是可选的,正在创建 存储库
class ProductRepository(上下文:上下文){
var dbms : LocalDAO = LocalDB.getInstance(context)?.localDataDao()!!
fun insertData(productEntity: LocalData) : Long{
return dbms.insertData(productEntity)
}
fun deleteData(productEntity: LocalData) : Int{
return dbms.deleteData(productEntity)
}
fun getAllData() : List<LocalData> {
return dbms.showAllProducts()
}
fun checkProductExist(id : Int) : Boolean{
return dbms.exists(id)
}
fun totalProductsInCart() : Long{
return dbms.totalProducts()
}
}