Android Jetpack应用指南学习笔记4之Room的简单使用

1.在Android中采用Sqlite作为数据库存储。Sqlite代码写起来繁琐且容易出错,所以开源社区里逐渐出现了各种ORM(Object Relational Mapping)库。这些开源ORM库都是为了方便Sqlite的使用,包括数据库的创建,升级,增删改查等。常见的ORM有ORMLite,GreenDAO等。Google也意识到了推出自家ORM的必要性,于是有了Room。

2.Room 包含 3 个主要组件: 

  • 数据库:包含数据库持有者,并作为应用已保留的持久关系型数据的底层连接的主要接入点。使用 @Database 注释的类应满足以下条件:是扩展 RoomDatabase 的抽象类。在注释中添加与数据库关联的实体列表。包含具有 0 个参数且返回使用 @Dao 注释的类的抽象方法。 在运行时,可以通过调用Room.databaseBuilder()或 Room.inMemoryDatabaseBuilder() 获取 Database 的实例。 

  • Entity:表示数据库中的表。 

  • DAO:包含用于访问数据库的方法。

应用使用 Room 数据库来获取与该数据库关联的数据访问对象 (DAO)。然后,应用使用每个 DAO 从数据库中获取实体,然后再将对这些实体的所有更改保存回数据库中。最后,应用使用实体来获取和设置与数据库中的表列相对应的值。

3.Room中常用注解说明:

  • @Entity:这是一个Model类,对应于数据库中的一张表。Entity类是Sqlite表结构在Java类的映射。 

  • @Dao:(Data Access Objects)数据访问对象,顾名思义,我们可以通过它来访问数据。一个Entity代表着一张表,而每张表都需要一个Dao对象,以方便对这张表进行各种操作(增删改查)

  • @Database:数据库对象,一般写成单例模式

4.Entity中的常用注解:

  • 属性:tableName:设置表名字。默认是类的名字。indices:设置索引。inheritSuperIndices:父类的索引是否会自动被当前类继承。

  • @foreignKeys:设置外键。

  • @PrimaryKey标签用于指定该字段作为表的主键。

  • @ColumnInfo标签可用于设置该字段存储在数据库表中的名字并指定字段的类型。

  • @Ignore标签用来告诉系统忽略该字段或者方法。

5.@ForeignKey属性

  • entity:parent实体类(引用外键的表的实体)。

  • parentColumns:parent外键列(要引用的外键列)。

  • childColumns:child外键列(要关联的列)。

  • onDelete:默认NO_ACTION,当parent里面有删除操作的时候,child表可以做的Action动作有:

    1. NO_ACTION:当parent中的key有变化的时候child不做任何动作。

    2. RESTRICT:当parent中的key有依赖的时候禁止对parent做动作,做动作就会报错。

    3. SET_NULL:当paren中的key有变化的时候child中依赖的key会设置为NULL。

    4. SET_DEFAULT:当parent中的key有变化的时候child中依赖的key会设置为默认值。

    5. CASCADE:当parent中的key有变化的时候child中依赖的key会跟着变化。

  • onUpdate:默认NO_ACTION,当parent里面有更新操作的时候,child表需要做的动作。Action动作方式和onDelete是一样的。

  • deferred:默认值false,在事务完成之前,是否应该推迟外键约束。这个怎么理解,当我们启动一个事务插入很多数据的时候,事务还没完成之前。当parent引起key变化的时候。可以设置deferred为ture。让key立即改变。

6.Dao中常用的注解:

  • @Query查询

  • @Insert插入

  • @Update更新

  • @Delete删除

7.@Insert注解属性onConflict: 

默认值是OnConflictStrategy.ABORT,表示当插入有冲突的时候的处理策略。

OnConflictStrategy封装了Room解决冲突的相关策略: 

  •  OnConflictStrategy.REPLACE:冲突策略是取代旧数据同时继续事务。

  •  OnConflictStrategy.ROLLBACK:冲突策略是回滚事务

  • OnConflictStrategy.ABORT:冲突策略是终止事务。

  • OnConflictStrategy.FAIL:冲突策略是事务失败。

  • OnConflictStrategy.IGNORE:冲突策略是忽略冲突。

8.Room在项目中的引入,在appbuild.gradle中加入room的相关依赖:

implementation "androidx.room:room-runtime:2.2.5"
annotationProcessor "androidx.room:room-compiler:2.2.5"

9.创建一个学生实体类,创建一张表

package com.example.roomdemo.entity;

import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.PrimaryKey;

/**
 * @author: njb
 * @date: 2020/8/28 0028 0:16
 * @desc:
 */
@Entity(tableName = "student")
public class Student {
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id", typeAffinity = ColumnInfo.INTEGER)
    public int id;

    @ColumnInfo(name = "name", typeAffinity = ColumnInfo.TEXT)
    public String name;

    @ColumnInfo(name = "age", typeAffinity = ColumnInfo.TEXT)
    public String age;

    /**
     * Room会使用这个构造器来存储数据,也就是当你从表中得到Student对象时候,Room会使用这个构造器
     */
    public Student(int id, String name, String age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    /**
     * 由于Room只能识别和使用一个构造器,如果希望定义多个构造器,你可以使用Ignore标签,让Room忽略这个构造器
     * 同样,@Ignore标签还可用于字段,使用@Ignore标签标记过的字段,Room不会持久化该字段的数据
     */
    @Ignore
    public Student(String name, String age) {
        this.name = name;
        this.age = age;
    }
}
10.创建dao文件接口:

package com.example.roomdemo.db;

import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;

import com.example.roomdemo.entity.Student;

import java.util.List;

/**
 * @author: njb
 * @date: 2020/8/28 0028 0:17
 * @desc:
 */
@Dao
public interface StudentDao {
    @Insert
    void insertStudent(Student student);

    @Delete
    void deleteStudent(Student student);

    @Update
    void updateStudent(Student student);

    @Query("SELECT * FROM student")
    List<Student> getStudentList();

    @Query("SELECT * FROM student WHERE id = :id")
    Student getStudentById(int id);
}
11.定义好Dao和实体类后,创建数据库:
package com.example.roomdemo.db;
import android.content.Context;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import com.example.roomdemo.entity.Student;

/**
 * @author: njb
 * @date: 2020/8/28 0028 0:19
 * @desc:
 */
@Database(entities = {Student.class}, version = 1)
public abstract class MyDatabase extends RoomDatabase {
    private static final String DATABASE_NAME = "student_db";

    private static MyDatabase databaseInstance;

    public static synchronized MyDatabase getInstance(Context context) {
        if (databaseInstance == null) {
            databaseInstance = Room
                    .databaseBuilder(context.getApplicationContext(), MyDatabase.class, DATABASE_NAME)
                    .build();
        }
        return databaseInstance;
    }

    public abstract StudentDao studentDao();
}

 12.数据库的使用:

//数据库初始化:

//插入数据

//查询数据

//删除数据

//更新数据

13.MainActiivty完整代码如下:
package com.example.roomdemo;

import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import com.example.roomdemo.adapter.StudentAdapter;
import com.example.roomdemo.db.MyDatabase;
import com.example.roomdemo.entity.Student;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private MyDatabase myDatabase;
    private List<Student> studentList;
    private StudentAdapter studentAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initDataBase();
        initAdapter();
    }

    private void initAdapter() {
        ListView lvStudent = findViewById(R.id.lvStudent);
        studentList = new ArrayList<>();
        studentAdapter = new StudentAdapter(MainActivity.this, studentList);
        lvStudent.setAdapter(studentAdapter);
        lvStudent.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                updateOrDeleteDialog(studentList.get(position));
                return false;
            }
        });
    }

    private void updateOrDeleteDialog(final Student student) {

        final String[] options = new String[]{"更新", "删除"};
        new AlertDialog.Builder(MainActivity.this)
                .setTitle("")
                .setItems(options, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        if (which == 0) {
                            openUpdateStudentDialog(student);
                        } else if (which == 1) {
                            new DeleteStudentTask(student).execute();
                        }
                    }
                }).show();
    }

    private void initDataBase() {
        myDatabase = MyDatabase.getInstance(MainActivity.this);
        new QueryStudentTask().execute();
    }

    public void insertData(View view) {
        //myDatabase.studentDao().insertStudent(new Student(name, age));
    }

    public void updateData(View view) {
        // myDatabase.studentDao().updateStudent(new Student(id, name, age));
    }


    public void deleteData(View view) {
        //myDatabase.studentDao().deleteStudent(new Student(id, name, age));
    }

    public void queryData(View view) {
    }


    public void addStudent(View view) {
        openAddStudentDialog();
    }

    private void openAddStudentDialog() {
        View customView = this.getLayoutInflater().inflate(R.layout.dialog_layout_student, null);
        final EditText etName = customView.findViewById(R.id.etName);
        final EditText etAge = customView.findViewById(R.id.etAge);

        final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        AlertDialog dialog = builder.create();
        dialog.setTitle("Add Student");
        dialog.setButton(DialogInterface.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (TextUtils.isEmpty(etName.getText().toString()) || TextUtils.isEmpty(etAge.getText().toString())) {
                    Toast.makeText(MainActivity.this, "输入不能为空", Toast.LENGTH_SHORT).show();
                } else {
                    new InsertStudentTask(etName.getText().toString(), etAge.getText().toString()).execute();
                }
            }
        });
        dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "CANCEL", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        dialog.setView(customView);
        dialog.show();
    }

    private void openUpdateStudentDialog(final Student student) {
        if (student == null) {
            return;
        }
        View customView = this.getLayoutInflater().inflate(R.layout.dialog_layout_student, null);
        final EditText etName = customView.findViewById(R.id.etName);
        final EditText etAge = customView.findViewById(R.id.etAge);
        etName.setText(student.name);
        etAge.setText(student.age);

        final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        AlertDialog dialog = builder.create();
        dialog.setTitle("Update Student");
        dialog.setButton(DialogInterface.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (TextUtils.isEmpty(etName.getText().toString()) || TextUtils.isEmpty(etAge.getText().toString())) {
                    Toast.makeText(MainActivity.this, "输入不能为空", Toast.LENGTH_SHORT).show();
                } else {
                    new UpdateStudentTask(student.id, etName.getText().toString(), etAge.getText().toString()).execute();
                }
            }
        });
        dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "CANCEL", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        dialog.setView(customView);
        dialog.show();
    }

    private class InsertStudentTask extends AsyncTask<Void, Void, Void> {
        String name;
        String age;

        public InsertStudentTask(final String name, final String age) {
            this.name = name;
            this.age = age;
        }

        @Override
        protected Void doInBackground(Void... arg0) {
            myDatabase.studentDao().insertStudent(new Student(name, age));
            studentList.clear();
            studentList.addAll(myDatabase.studentDao().getStudentList());
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            studentAdapter.notifyDataSetChanged();
        }
    }

    private class UpdateStudentTask extends AsyncTask<Void, Void, Void> {
        int id;
        String name;
        String age;

        public UpdateStudentTask(final int id, final String name, final String age) {
            this.id = id;
            this.name = name;
            this.age = age;
        }

        @Override
        protected Void doInBackground(Void... arg0) {
            myDatabase.studentDao().updateStudent(new Student(id, name, age));
            studentList.clear();
            studentList.addAll(myDatabase.studentDao().getStudentList());
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            studentAdapter.notifyDataSetChanged();
        }
    }

    private class DeleteStudentTask extends AsyncTask<Void, Void, Void> {
        Student student;

        public DeleteStudentTask(Student student) {
            this.student = student;
        }

        @Override
        protected Void doInBackground(Void... arg0) {
            myDatabase.studentDao().deleteStudent(student);
            studentList.clear();
            studentList.addAll(myDatabase.studentDao().getStudentList());
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            studentAdapter.notifyDataSetChanged();
        }
    }

    private class QueryStudentTask extends AsyncTask<Void, Void, Void> {
        public QueryStudentTask() {

        }

        @Override
        protected Void doInBackground(Void... arg0) {
            studentList.clear();
            studentList.addAll(myDatabase.studentDao().getStudentList());
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            studentAdapter.notifyDataSetChanged();
        }
    }
}

14.最终实现的效果图如下:

15.项目源码地址如下:smile drily/RoomDemo

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值