Andriod --- JetPack (七):Room + ViewModel + LiveData 增删改查实例
1.Andriod — JetPack (一):初識 JetPack
2.Andriod — JetPack (二):LifeCycle 的誕生
3.Andriod — JetPack (三):ViewModel 的誕生
4.Andriod — JetPack (四):BaseObservable 與 ObservableField 雙向綁定
5.Andriod — JetPack (五):DataBinding + LiveData +ViewModel 簡單實例
6.Andriod — JetPack (六):Room 增刪改查
7.Andriod — JetPack (七):Room + ViewModel + LiveData 增刪改查實例
一、前言
1.為什么使用 LiveData + ViewModel ?
每當數據庫數據發生變化時,都需要開啟一個工作線程去重新獲取數據庫中的數據。所以,當數據變化時,我們可以通過 LiveData 通知 View 層,實現數據的自動更新。
2.圖解
二、代碼實例
build.gradle
// Room implementation "androidx.room:room-runtime:2.2.5" annotationProcessor "androidx.room:room-compiler:2.2.5" implementation 'androidx.recyclerview:recyclerview:1.0.0'activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"app:layout_constraintGuide_percent="0.1" /><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"app:layout_constraintGuide_percent="0.2" /><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline4"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"app:layout_constraintGuide_percent="0.5" /><Buttonandroid:id="@+id/button7"android:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="mInsert"android:text="增加"app:layout_constraintBottom_toTopOf="@+id/guideline2"app:layout_constraintEnd_toStartOf="@+id/guideline4"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /><Buttonandroid:id="@+id/button8"android:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="mUpdate"android:text="修改"app:layout_constraintBottom_toTopOf="@+id/guideline2"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="@+id/guideline4"app:layout_constraintTop_toTopOf="parent" /><Buttonandroid:id="@+id/button9"android:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="mDelete"android:text="刪除"app:layout_constraintBottom_toTopOf="@+id/guideline3"app:layout_constraintEnd_toStartOf="@+id/guideline4"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="@+id/guideline2" /><Buttonandroid:id="@+id/button10"android:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="mClear"android:text="清空"app:layout_constraintBottom_toTopOf="@+id/guideline3"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="@+id/guideline4"app:layout_constraintTop_toTopOf="@+id/guideline2" /><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/rv_01"android:layout_width="match_parent"android:layout_height="wrap_content"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="@+id/guideline3" /> </androidx.constraintlayout.widget.ConstraintLayout>item.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="wrap_content"><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"app:layout_constraintGuide_percent="0.2" /><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline5"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"app:layout_constraintGuide_percent="0.8" /><TextViewandroid:id="@+id/tvId"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="1"app:layout_constraintBottom_toTopOf="@+id/guideline7"app:layout_constraintEnd_toStartOf="@+id/guideline"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /><TextViewandroid:id="@+id/name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Jack"app:layout_constraintBottom_toTopOf="@+id/guideline7"app:layout_constraintEnd_toStartOf="@+id/guideline5"app:layout_constraintStart_toStartOf="@+id/guideline"app:layout_constraintTop_toTopOf="parent" /><TextViewandroid:id="@+id/age"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="18"app:layout_constraintBottom_toTopOf="@+id/guideline7"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="@+id/guideline5"app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>Student.java
package com.example.room2;import androidx.room.ColumnInfo; import androidx.room.Entity; import androidx.room.Ignore; import androidx.room.PrimaryKey;@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;public Student(int id, String name, int age) {this.id = id;this.name = name;this.age = age;}@Ignorepublic Student(String name, int age) {this.name = name;this.age = age;}@Ignorepublic Student(int id) {this.id = id;} }StudentDao.java
package com.example.room2;import androidx.lifecycle.LiveData; import androidx.room.Dao; import androidx.room.Delete; import androidx.room.Insert; import androidx.room.Query; import androidx.room.Update;import java.util.List;@Dao public interface StudentDao {@Insertvoid insertStudent(Student... students); // 可以傳入多個 Student@Deletevoid deleteStudent(Student... students);@Query("DELETE FROM student")void deleteAllStudent();@Updatevoid updateStudent(Student... students);@Query("SELECT * FROM student")LiveData<List<Student>> getAllStudentsLive();@Query("SELECT * FROM student WHERE id = :id")List<Student> getStudentById(Integer id); }MyDataBase.java
package com.example.room2;import android.content.Context;import androidx.room.Database; import androidx.room.Room; import androidx.room.RoomDatabase;// 一定是抽象類 @Database(entities = {Student.class}, version = 1, exportSchema = false) public abstract class MyDataBase extends RoomDatabase {private static final String DATABASE_NAME = "my_db.db";private static MyDataBase mInstance;// 構建 database 單例public static synchronized MyDataBase getInstance(Context context) {if(mInstance == null) {mInstance = Room.databaseBuilder(context.getApplicationContext(), MyDataBase.class, DATABASE_NAME)//.allowMainThreadQueries() // 允許在主線程操作數據庫.build();}return mInstance;}public abstract StudentDao getStudentDao(); }StudentRepository.java
package com.example.room2;import android.content.Context; import android.os.AsyncTask;import androidx.lifecycle.LiveData;import java.util.List;public class StudentRepository {private StudentDao studentDao;public StudentRepository(Context context) {MyDataBase dataBase = MyDataBase.getInstance(context);this.studentDao = dataBase.getStudentDao();this.studentDao = studentDao;}public void insertStudent(Student... students) {new InsertStudentTask(studentDao).execute(students);}public void deleteStudent(Student... students) {new DeleteStudentTask(studentDao).execute(students);}public void deleteAllStudents() {new DeleteAllStudentsTask(studentDao).execute();}public void updateStudent(Student... students) {new UpdateStudentTask(studentDao).execute(students);}public LiveData<List<Student>> getAllStudentsLive() {return studentDao.getAllStudentsLive();}// 異步線程添加學生class InsertStudentTask extends AsyncTask<Student, Void, Void> {private StudentDao studentDao;public InsertStudentTask(StudentDao studentDao) {this.studentDao = studentDao;}@Overrideprotected Void doInBackground(Student... students) {studentDao.insertStudent(students);return null;}}// 異步修改學生class UpdateStudentTask extends AsyncTask<Student, Void, Void> {private StudentDao studentDao;public UpdateStudentTask(StudentDao studentDao) {this.studentDao = studentDao;}@Overrideprotected Void doInBackground(Student... students) {studentDao.updateStudent(students);return null;}}// 異步刪除學生class DeleteStudentTask extends AsyncTask<Student, Void, Void> {private StudentDao studentDao;public DeleteStudentTask(StudentDao studentDao) {this.studentDao = studentDao;}@Overrideprotected Void doInBackground(Student... students) {studentDao.deleteStudent(students);return null;}}// 異步刪除所有學生class DeleteAllStudentsTask extends AsyncTask<Void, Void, Void> {private StudentDao studentDao;public DeleteAllStudentsTask(StudentDao studentDao) {this.studentDao = studentDao;}@Overrideprotected Void doInBackground(Void... Void) {studentDao.deleteAllStudent();return null;}}}StudentViewModel.java
package com.example.room2;import android.app.Application;import androidx.annotation.NonNull; import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.LiveData;import java.util.List;public class StudentViewModel extends AndroidViewModel {private StudentRepository repository;public StudentViewModel(@NonNull Application application) {super(application);this.repository = new StudentRepository(application);}public void insertStudent(Student... students) {repository.insertStudent(students);}public void deleteAllStudents() {repository.deleteAllStudents();}public void deleteStudent(Student... students) {repository.deleteStudent(students);}public void updateStudent(Student... students) {repository.updateStudent(students);}public LiveData<List<Student>> getAllStudentsLive() {return repository.getAllStudentsLive();}}MainActivity.java
package com.example.room2;import android.os.AsyncTask; import android.os.Bundle; import android.view.View;import androidx.appcompat.app.AppCompatActivity; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView;import java.util.ArrayList; import java.util.List;public class MainActivity extends AppCompatActivity {private StudentRecycleViewAdapter adapter;private StudentDao studentDao;private StudentViewModel studentViewModel;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);List<Student> students = new ArrayList<>();RecyclerView recyclerView = findViewById(R.id.rv_01);adapter = new StudentRecycleViewAdapter(students);recyclerView.setLayoutManager(new LinearLayoutManager(this));recyclerView.setAdapter(adapter);// 得到 ViewModelstudentViewModel = new ViewModelProvider(this, new ViewModelProvider.AndroidViewModelFactory(getApplication())).get(StudentViewModel.class);// 自動更新操作,給 LiveData 監聽studentViewModel.getAllStudentsLive().observe(this, new Observer<List<Student>>() {@Overridepublic void onChanged(List<Student> students) {adapter.setStudents(students);adapter.notifyDataSetChanged();}});}// Room 不允許在主線程操作數據庫,如果非在主線程操作數據庫,請修改 MyDataBase 文件// 增加public void mInsert(View view) {Student s1 = new Student("Jack", 20);Student s2 = new Student("Rose", 22);studentViewModel.insertStudent(s1, s2);}// 刪除public void mDelete(View view) {Student s1 = new Student(4);studentViewModel.deleteStudent(s1);}// 修改public void mUpdate(View view) {Student s1 = new Student(3, "Jason", 21);studentViewModel.updateStudent(s1);}public void mClear(View view) {studentViewModel.deleteAllStudents();} }StudentRecycleViewAdapter.java
package com.example.room2;import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView;import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView;import java.util.List;public class StudentRecycleViewAdapter extends RecyclerView.Adapter<StudentRecycleViewAdapter.MyViewHolder> {List<Student> students;public void setStudents(List<Student> students) {this.students = students;}public StudentRecycleViewAdapter(List<Student> students) {this.students = students;}@NonNull@Overridepublic MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View root = LayoutInflater.from(parent.getContext()).inflate(R.layout.item,parent, false);return new MyViewHolder(root);}@Overridepublic void onBindViewHolder(@NonNull MyViewHolder holder, int position) {Student student = students.get(position);holder.tvId.setText(String.valueOf(student.id));holder.name.setText(student.name);holder.age.setText(String.valueOf(student.age));}@Overridepublic int getItemCount() {return students == null ? 0 :students.size();}public class MyViewHolder extends RecyclerView.ViewHolder {private TextView tvId, name, age;public MyViewHolder(View view) {super(view);tvId = view.findViewById(R.id.tvId);name = view.findViewById(R.id.name);age = view.findViewById(R.id.age);}} } 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的Andriod --- JetPack (七):Room + ViewModel + LiveData 增删改查实例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Andriod --- JetPack
- 下一篇: 数据特征处理方法