用一个案例记录一下room笔记
实现本地数据库的学生列表的增删改查

按添加,弹出对话框,填入信息后添加一条数据到数据库,删除所有点击后清空student表下的数据,点击列表条目弹出修改框修改用户信息。当然每一次进入、添加、删除、修改等操作后自动查询用户信息并更新列表数据。
编写数据库先按3步走,entity -》Dao -》DataBase
引入room
implementation 'androidx.room:room-runtime:2.3.0-alpha03'
annotationProcessor 'androidx.room:room-compiler:2.3.0-alpha03'
1、我们先搭好实例类。
@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.INTEGER)
public int age;
//room 需要的构造方法
public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
@Ignore
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Ignore //添加忽略标签,这样的话room不会管这个方法或者变量
public Student(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
关于注释,Entity是对表的标注,可以命名表的名称,PrimaryKey是主键它可以设置自增长,ColumnInfo是对列的注释,可能重命名列的名称和类型。Ignore是忽略的意思。
接下来是Dao
@Dao
public interface StudentDao {
@Insert
void insertStudent(Student... students);
@Delete
void deleteStudent(Student... students);
@Query("DELETE FROM student")
void deleteAllStudent();
@Update
void updateStudent(Student... students);
@Query("SELECT * FROM student")
List<Student> getAllStudent();
@Query("SELECT * FROM student WHERE id = :id")
List<Student> getAllStudentByID(int id);
@Query("SELECT * FROM student")
LiveData<List<Student>> getAllStudentByLiveData();
}
首先这是一个接口,具体的实现交给Room生成,Dao注释必须加上,否则编译报错。值得强调的一点,Query注释是可以写删除、修改等sql语句的。
接下来是database
@Database(entities = {Student.class}, version = 1,exportSchema = false)
public abstract class MyDataBese extends RoomDatabase {
private static MyDataBese instance;
private static final String mDBName="my_db.db";
public static synchronized MyDataBese getInstance(Context context) {
if(instance == null){
instance = Room.databaseBuilder(context.getApplicationContext(),
MyDataBese.class,
mDBName)
.build();
}
return instance;
}
public abstract StudentDao getStudentDao();
}
他是一个抽象类,因为getStudentDao是由room自动生成。这里用Room.databaseBuilder生成了最简单的配置。Database注释里面entities 就是代表自己数据库里有的表实例,exportSchema 是额外生成的数据库升级文件json数据。后面讲到数据库升级再设置为TRUE。
对了记住一点,room操作数据时默认需要在子线程下进行,否则会报错,如果需要在主线程进行,那么就添加allowMainThreadQueries()设置。
instance = Room.databaseBuilder(context.getApplicationContext(),
MyDataBese.class,
mDBName)
.allowMainThreadQueries()
.build();
数据库准备好了,那就准备我们的activity吧,当然需要结合我们的viewmodel、databinding、livedata去做。
public class RoomActivity extends AppCompatActivity {
private ActivityRoomBinding mBinding;
private MyViewModel mViewModel;
private MyAdapter mAdapter;
private StudentDao mStudentDao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_room);
mBinding.setOnClick(this);
mViewModel = new ViewModelProvider(this, new ViewModelProvider.AndroidViewModelFactory(getApplication())).get(MyViewModel.class);
initView();
initDataBese();
}
private void initDataBese() {
mStudentDao = MyDataBese.getInstance(this).getStudentDao();
mStudentDao.getAllStudentByLiveData().observe(this, new Observer<List<Student>>() {
@Override
public void onChanged(List<Student> students) {
Log.d("yanjin","size = "+students.size());
mAdapter.updateList(students);
}
});
}
private void initView() {
//initRecycleview
initRecycleview();
}
private void initRecycleview() {
mBinding.mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mAdapter = new MyAdapter(mViewModel.getStudents().getValue());
mAdapter.setListener(new MyAdapter.OnLongClickListener() {
@Override
public void onLongClick(Student student) {
//update student
updateStudent(student);
}
});
mBinding.mRecyclerView.setAdapter(mAdapter);
}
public void onClickView(View view){
int id = view.getId();
if(id == R.id.add){
addStudent();
}else if(id == R.id.delete_all){
DeleteAllStudentAsyncTask task = new DeleteAllStudentAsyncTask(mStudentDao);
task.execute();
}
}
private void addStudent() {
View view = getLayoutInflater().inflate(R.layout.add_student_layout,null);
AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setTitle("添加学生")//设置对话框 标题
.setView(view);
builder.create();
final AlertDialog dialog = builder.show();
final EditText editName = view.findViewById(R.id.et_name);
final EditText editAge = view.findViewById(R.id.et_age);
view.findViewById(R.id.btn_ok).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
String ages = editAge.getText().toString().trim();
//有可能出现string转int出错
Integer age = Integer.valueOf(ages);
String name = editName.getText().toString().trim();
Student student = new Student(name,age);
AddStudentAsyncTask task = new AddStudentAsyncTask(mStudentDao);
task.execute(student);
dialog.dismiss();
}catch (Exception e){
e.printStackTrace();
}
}
});
}
private void updateStudent(Student student) {
View view = getLayoutInflater().inflate(R.layout.update_student_layout,null);
AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setTitle("添加学生")//设置对话框 标题
.setView(view);
builder.create();
final AlertDialog dialog = builder.show();
final EditText editName = view.findViewById(R.id.et_name);
final EditText editAge = view.findViewById(R.id.et_age);
final int id = student.getId();
editName.setText(student.getName());
editAge.setText(student.getAge()+"");
view.findViewById(R.id.btn_ok).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
String ages = editAge.getText().toString().trim();
//有可能出现string转int出错
Integer age = Integer.valueOf(ages);
String name = editName.getText().toString().trim();
Student student = new Student(id,name,age);
UpdateStudentAsyncTask task = new UpdateStudentAsyncTask(mStudentDao);
task.execute(student);
dialog.dismiss();
}catch (Exception e){
e.printStackTrace();
}
}
});
}
}
viewmodel
public class MyViewModel extends ViewModel {
private MutableLiveData<List<Student>> mStudents;
public MutableLiveData<List<Student>> getStudents() {
if(mStudents == null){
mStudents = new MutableLiveData<>();
mStudents.setValue(new ArrayList<Student>());
}
return mStudents;
}
}
MyAdapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private List<Student> list;
public MyAdapter(List<Student> list){
this.list = list;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
RoomItemLayoutBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.room_item_layout, parent, false);
return new ViewHolder(binding);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
final Student student = list.get(position);
holder.mBinding.setStudent(student);
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if(mListener != null){
mListener.onLongClick(student);
}
return false;
}
});
}
@Override
public int getItemCount() {
return list.size();
}
public void updateList(List<Student> students) {
list.clear();
list.addAll(students);
notifyDataSetChanged();
}
public class ViewHolder extends RecyclerView.ViewHolder {
RoomItemLayoutBinding mBinding;
public ViewHolder(@NonNull RoomItemLayoutBinding binding) {
super(binding.getRoot());
mBinding = binding;
}
}
public interface OnLongClickListener{
void onLongClick(Student student);
}
private OnLongClickListener mListener;
public void setListener(OnLongClickListener mListener) {
this.mListener = mListener;
}
}
AddStudentAsyncTask
public class AddStudentAsyncTask extends AsyncTask<Student, Void, Void>{
private StudentDao mStudentDao;
public AddStudentAsyncTask(StudentDao dao){
mStudentDao = dao;
}
@Override
protected Void doInBackground(Student... students) {
mStudentDao.insertStudent(students);
return null;
}
}
DeleteAllStudentAsyncTask
public class DeleteAllStudentAsyncTask extends AsyncTask<Void, Void, Void>{
private StudentDao mStudentDao;
public DeleteAllStudentAsyncTask(StudentDao dao){
mStudentDao = dao;
}
@Override
protected Void doInBackground(Void... voids) {
mStudentDao.deleteAllStudent();
return null;
}
}
UpdateStudentAsyncTask
public class UpdateStudentAsyncTask extends AsyncTask<Student, Void, Void>{
private StudentDao mStudentDao;
public UpdateStudentAsyncTask(StudentDao dao){
mStudentDao = dao;
}
@Override
protected Void doInBackground(Student... students) {
mStudentDao.updateStudent(students);
return null;
}
}
接下来的弹窗布局和列表条目布局如下:
add_student_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:inputType="text"
android:hint="请输入名字"/>
<EditText
android:id="@+id/et_age"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:inputType="number"
android:hint="请输入年龄"/>
<Button
android:id="@+id/btn_ok"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ok"/>
</LinearLayout>
update_student_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:inputType="text"
android:hint="请输入名字"/>
<EditText
android:id="@+id/et_age"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:inputType="number"
android:hint="请输入年龄"/>
<Button
android:id="@+id/btn_ok"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ok"/>
</LinearLayout>
room_item_layout.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="student"
type="com.example.myapplication.jetpack.room.Student" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
xmlns:tools="http://schemas.android.com/tools">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="id"
android:text="@{String.valueOf(student.id)}"
android:textSize="18sp"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:textColor="@android:color/black"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="name"
android:text="@{student.name}"
android:textSize="18sp"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:textColor="@android:color/black"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="age"
android:text="@{String.valueOf(student.age)}"
android:textSize="18sp"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
android:textColor="@android:color/black"/>
</RelativeLayout>
</layout>
网友评论