简体   繁体   English

实施房间数据库 (Android)

[英]Implementing the Room Database (Android)

I like to know how to properly integrate the Room Library within an Android Application.我想知道如何在 Android 应用程序中正确集成 Room Library。 Some articles I have seen uses a Singleton approach using a Respository for database calls, while other uses some form of Dependecy Injection (Dagger 2).我看到的一些文章使用 Singleton 方法,使用 Respository 进行数据库调用,而其他文章则使用某种形式的 Dependecy Injection (Dagger 2)。 I like to know the proper integration of this library?我想知道这个库的正确集成?

Thanks谢谢

Room Basics房间基础

The Room library acts as an abstract layer for underlying SQLite database. Room 库充当底层 SQLite 数据库的抽象层。 Thus, Room annotations are used:因此,使用 Room 注释:

  1. To Database and Entities where entities are POJO classes representing table structures.到数据库和实体,其中实体是表示表结构的 POJO 类。
  2. To specify operation for retrieval, updation and deletion.指定检索、更新和删除操作。
  3. To add constraints, such as foreign keys.添加约束,例如外键。
  4. Support for LiveData.支持 LiveData。

There are 3 major components in Room Room 有 3 个主要组件

  1. Entity : A class annotated with the @Entity annotation is mapped to a table in database.实体:用@Entity 注释的类映射到数据库中的表。 Every entity is persisted in its own table and every field in class represents the column name.每个实体都保存在自己的表中,类中的每个字段都代表列名。

tableName attribute is used to define the name of the table Every entity class must have at-least one Primary Key field, annotated with @PrimaryKey Fields in entity class can be annotated with @ColumnInfo(name = “name_of_column”) annotation to give specific column names tableName 属性用于定义表的名称 每个实体类必须至少有一个 Primary Key 字段,用 @PrimaryKey 注释 实体类中的字段可以用 @ColumnInfo(name = “name_of_column”) 注释给出特定列名字

  1. DAO : Data Access Object is either be an interface or an abstract class annotated with @Doa annotation, containing all the methods to define the operations to be performed on data. DAO :数据访问对象要么是一个接口,要么是一个用@Doa 注释的抽象类,包含定义要对数据执行的操作的所有方法。 The methods can be annotated with方法可以用注释

@Query to retrieve data from database @Query 从数据库中检索数据

@Insert to insert data into database @Insert 将数据插入数据库

@Delete to delete data from database @Delete 从数据库中删除数据

@Update to update data in database @Update 更新数据库中的数据

  1. Database : Database is a container for tables.数据库:数据库是表的容器。 An abstract class annotated with @Database annotation is used to create a database with given name along with database version.使用@Database 注释的抽象类用于创建具有给定名称和数据库版本的数据库。

为了更好地理解看这张图

Add these dependencies :添加这些依赖项:

    dependencies {
    // Room dependencies
      compile 'android.arch.persistence.room:runtime:1.0.0'
      annotationProcessor 'android.arch.persistence.room:compiler:1.0.0'
    }

Create Entity创建实体

Before creating a database, Let's create an Entity, named as Note and later, Objects of this class will be added to database.在创建数据库之前,让我们创建一个实体,命名为 Note,稍后,该类的对象将被添加到数据库中。

    @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 + '\'' +
                '}';
    }}

Creating DAOs创建 DAO

DAOs define all methods to access database, annotated with @Dao annotation. DAO 定义了访问数据库的所有方法,并使用 @Dao 注释进行了注释。 The DAO acts as a contract to perform CRUD operations on data within a database. 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

}

Create Database创建数据库

Now, we have table defined as Entity and CRUD methods defined via NoteDao.现在,我们将表定义为实体,并通过 NoteDao 定义了 CRUD 方法。 The last piece of the database puzzle is the database itself.数据库难题的最后一部分是数据库本身。

@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;
}

}

Implement Database Interactions实现数据库交互

The below snippet will demonstrate the working of insert, update, and delete functionality using the Room database.下面的代码片段将演示使用 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);
          }
      }

}

}

Retrieve And Display NoteList检索和显示 NoteList

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));

}

}

Update Note更新说明

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);
            }
        });
    }

}

Delete Note删除笔记

noteDatabase.getNoteDao().deleteNote(notes.get(pos));
adapterObj.notifyDataSetChanged();

咨询官方文档怎么样。

ROOM Database房间数据库

  • Room is an ORM (Object Relational Mapper) for SQLite database in Android developement and part of Android Jetpack. Room 是 Android 开发中 SQLite 数据库的 ORM(对象关系映射器),也是 Android Jetpack 的一部分。
  • Provides an abstraction layer over SQLite database在 SQLite 数据库上提供抽象层
  • Amount of boilerplate code is reduced样板代码量减少
  • Compile-time verification of SQL queries SQL 查询的编译时验证

ROOM Database components ROOM 数据库组件

  • It has 3 main components Entity, Database, DAO.它有 3 个主要组件实体、数据库、DAO。
  • Entity is data class annotated with @Entity is like creating a table in SQLite and the variables in the model class are like columns in the table. Entity是用@Entity 注解的数据类,就像在 SQLite 中创建一个表,模型类中的变量就像表中的列。
  • Database is an abstract class which extends RoomDatabase and has list of entities associated with the database. Database是一个抽象类,它扩展了 RoomDatabase 并具有与数据库关联的实体列表。
  • DAO(Data Access Object) is an interface which defines the operations to be performed in our database. DAO(数据访问对象)是一个接口,它定义了要在我们的数据库中执行的操作。

ROOM Database Implementation ROOM 数据库实现

  • Step 1 creating Entity data class Step 1 创建实体数据类

    @Entity(tableName = "yourOwnTableName") @Entity(tableName = "yourOwnTableName")

    data class LocalData(数据类 LocalData(

     val column1: String?, val column2: String?, @PrimaryKey(autoGenerate = true) val product_local_id: Int?= null

    ) )

  • Step 2 creating Database步骤 2 创建数据库

    @Database(entities = [LocalData::class], version = 1, exportSchema = false) @TypeConverters @Database(实体 = [LocalData::class],版本 = 1,exportSchema = false)@TypeConverters

    abstract class LocalDB : RoomDatabase() {抽象类 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 } }

    } }

  • Step 3 creating DAO步骤 3 创建DAO

    @Dao interface LocalDAO { @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

    } }

  • Step 4 is optional is creating repository第 4 步是可选的,是创建存储库

class ProductRepository(context: Context) {类 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()
}

} }

step1 add the dependency in your build.gradle step1 在您的 build.gradle 中添加依赖项

def room_version = "2.2.5"

//better to replace new version
implementation "android.arch.lifecycle:extensions:1.1.0"
implementation "androidx.room:room-runtime:$room_version"
implementation "androidx.room:room-rxjava2:$room_version"
implementation "androidx.room:room-guava:$room_version"

// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel:2.3.1"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata:2.3.1"


annotationProcessor "androidx.room:room-compiler:$room_version"
testImplementation "androidx.room:room-testing:$room_version"

I think the best place is codelabs, it has a simple implementation, as well as a more complex one.我认为最好的地方是 codelabs,它有一个简单的实现,也有一个更复杂的实现 All using Room.全部使用Room。

Edit: Above links seems to be removed.编辑:上面的链接似乎已被删除。 Here are a couple of resources to replace that:以下是一些替代资源的资源:

  1. Android room with a view 景观房
  2. Room + LiveData + ViewModel Room + LiveData + ViewModel

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM