Android--Jetpack--数据库Room详解二

本是青灯不归客,却因浊酒恋红尘

一,基本使用

关于Room数据库的基本使用,请参考文章Android--Jetpack--数据库Room详解一-CSDN博客

二,Room与ViewModle,LiveData的结合使用

LiveData与ViewModle的使用,请参考文章Android--Jetpack--LiveData-CSDN博客

我们通过结合Room与LiveData和ViewModle的使用,可以使当我们的数据库发生变化的时候,自动的去更新UI。

下面来看一个简单的使用案例:

1,还是 Android--Jetpack--数据库Room详解一-CSDN博客

中创建的数据库,表还是YuanZhen这张表, 我们把YuanZhenDao这个Dao类添加一个新的方法,使得可以查询到LiveData包装的集合:

java 复制代码
@Dao
public interface YuanZhenDao {

    @Insert
    void insert(YuanZhen... yuanzhens);

    @Delete
    void delete(YuanZhen yuanZhen);

    @Update
    void update(YuanZhen yuanZhen);

    @Query("select * from YuanZhen")
    List<YuanZhen> getAll();

    @Query("select * from YuanZhen where name like :name")
    YuanZhen getByName(String name);

    @Query("select * from YuanZhen where age in(:ages)")
    List<YuanZhen> getByAges(int[] ages);

    @Query("select name,address from YuanZhen ")
    public List<YuanZhenNew> getNew();

   @Query("select * from YuanZhen")
    LiveData<List<YuanZhen>> getAllLiveDataYZ();
}

2,将数据库MyDatabase修改为单例模式:

java 复制代码
@Database(entities = {YuanZhen.class},version = 1)
public abstract class MyDatabase extends RoomDatabase {

    private static MyDatabase instance;
    public static synchronized MyDatabase getInstance(Context context){
        if(instance==null){
            instance= Room.databaseBuilder(context.getApplicationContext(),MyDatabase.class
                            ,"YuanZhenDb")
                    .build();

        }
        return instance;
    }

    public abstract YuanZhenDao yuanZhenDao();

}

3,创建一个包装类,包装LiveData给ViewModel使用:

java 复制代码
public class YuanZhenDecorate {

    private LiveData<List<YuanZhen>> liveDataAllYZ;

    private YuanZhenDao yuanZhenDao;

    public YuanZhenDecorate(Context context) {
        yuanZhenDao =MyDatabase.getInstance(context).yuanZhenDao();
        if(liveDataAllYZ==null){
            liveDataAllYZ=yuanZhenDao.getAllLiveDataYZ();
        }
    }
    void insert(YuanZhen... yuanZhens){
        yuanZhenDao.insert(yuanZhens);
    }
    void delete(YuanZhen yuanZhen){
        yuanZhenDao.delete(yuanZhen);
    }
    void update(YuanZhen yuanZhen){
        yuanZhenDao.update(yuanZhen);
    }
    List<YuanZhen> getAll(){
        return yuanZhenDao.getAll();
    }

    LiveData<List<YuanZhen>> getAllLiveDataYZ(){
        return yuanZhenDao.getAllLiveDataYZ();
    }

}

4,创建一个viewmodle:

java 复制代码
public class YZViewModdel extends AndroidViewModel {

    private YuanZhenDecorate yuanZhenDecorate;

    public YZViewModdel(@NonNull Application application) {
        super(application);
        yuanZhenDecorate =new YuanZhenDecorate(application);
    }
    void insert(YuanZhen... yuanZhens){
        yuanZhenDecorate.insert(yuanZhens);
    }
    void delete(YuanZhen yuanZhen){
        yuanZhenDecorate.delete(yuanZhen);
    }
    void update(YuanZhen yuanZhen){
        yuanZhenDecorate.update(yuanZhen);
    }
    List<YuanZhen> getAll(){
        return yuanZhenDecorate.getAll();
    }

    LiveData<List<YuanZhen>> getAllLiveDataYZ(){
        return yuanZhenDecorate.getAllLiveDataYZ();
    }

}

5,创建一个recyclerview的adapter:

java 复制代码
public class MyAdapter extends RecyclerView.Adapter {
    private LayoutInflater mLayoutInflater;

    private List<YuanZhen> mList;

    public MyAdapter(Context context,List<YuanZhen> mList) {
        mLayoutInflater =LayoutInflater.from(context);
        this.mList =mList;
    }

    public void setData(List<YuanZhen> mList) {
        this.mList = mList;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new ViewHolder(mLayoutInflater.inflate(R.layout.item, parent, false));
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        ((ViewHolder)holder).mTxt.setText(mList.get(position).getName());
    }

    @Override
    public int getItemCount() {
        if(mList!=null){
            return mList.size();
        }
        return 0;
    }

    class ViewHolder extends RecyclerView.ViewHolder {

        TextView mTxt;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            mTxt = (TextView) itemView.findViewById(R.id.txt);
        }
    }


}

6,activity的xml布局:

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.recyclerview.widget.RecyclerView
        android:id="@+id/rv_room"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

7,item的xml布局:

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <TextView
        android:id="@+id/txt"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:textSize="16sp"/>


</RelativeLayout>

8,使用:

java 复制代码
public class MainActivity extends AppCompatActivity {

    StudentViewModel studentViewModel;
    ListView listView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView = findViewById(R.id.listView);

        studentViewModel = ViewModelProviders.of(this).get(StudentViewModel.class);
        studentViewModel.getAllLiveDataStudent().observe(this, new Observer<List<Student>>() {
            @Override
            public void onChanged(List<Student> students) {
                listView.setAdapter(new GoodsAdapter(MainActivity.this, students));
            }
        });

        for (int i = 0; i < 50; i++) {
            studentViewModel.insert(new Student("jett", "123", 1));
        }

        new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 50; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    studentViewModel.update(new Student(6, "jett" + i, "123", 1));
                }
            }
        }.start();

    }
}

9,运行:

三,数据库的升级

1,强制升级,执行之后数据库的结构会发生变化,但是数据库的数据会丢失。

这种情况比较适合toB开发,数据库版本高降到低的情况,紧急发一版新的程序给现场升级。

使用 :fallbackToDestructiveMigration()

java 复制代码
@Database(entities = {YuanZhen.class},version = 2)
public abstract class MyDatabase extends RoomDatabase {

    private static MyDatabase instance;
    public static synchronized MyDatabase getInstance(Context context){
        if(instance==null){
            instance= Room.databaseBuilder(context.getApplicationContext(),MyDatabase.class
                            ,"YuanZhenDb")
                    //强制升级
                    .fallbackToDestructiveMigration()
                    .build();

        }
        return instance;
    }

    public abstract YuanZhenDao yuanZhenDao();

}

2,一般的升级方式

假如我们要增加一个字段price:

java 复制代码
@Entity
public class YuanZhen {

    @PrimaryKey(autoGenerate = true)
    private int id;

    @ColumnInfo(name ="name")
    private String name;

    @ColumnInfo(name ="age")
    private int age;

    @ColumnInfo(name ="address")
    private String address;

    @ColumnInfo(name = "price")
    private int price;

    @Ignore
    private String sex;

    public YuanZhen(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getAddress() {
        return address;
    }

    @Override
    public String toString() {
        return "YuanZhen{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                ", sex='" + sex + '\'' +
                '}';
    }
}

在MyDatabase中增加升级功能:

java 复制代码
@Database(entities = {YuanZhen.class},version = 2,exportSchema = false)
public abstract class MyDatabase extends RoomDatabase {

    private static MyDatabase instance;
    public static synchronized MyDatabase getInstance(Context context){
        if(instance==null){
            instance= Room.databaseBuilder(context.getApplicationContext(),MyDatabase.class
                            ,"YuanZhenDb")
                    //强制升级
                   // .fallbackToDestructiveMigration()
                    .addMigrations(MIGRATION_1_2)
                    .build();

        }
        return instance;
    }

    public abstract YuanZhenDao yuanZhenDao();

    static final Migration MIGRATION_1_2=new Migration(1,2) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            //在这里用sql脚本完成数据变化
            database.execSQL("alter table yuanzhen add column price integer not null default 1");
        }
    };

}

这里和greendao最大的不同就是,这里需要自己去写升级脚本,虽然增加了工作量,但是也更加灵活了。

相关推荐
Eastsea.Chen2 小时前
MTK Android12 user版本MtkLogger
android·framework
长亭外的少年9 小时前
Kotlin 编译失败问题及解决方案:从守护进程到 Gradle 配置
android·开发语言·kotlin
建群新人小猿11 小时前
会员等级经验问题
android·开发语言·前端·javascript·php
1024小神13 小时前
tauri2.0版本开发苹果ios和安卓android应用,环境搭建和最后编译为apk
android·ios·tauri
兰琛13 小时前
20241121 android中树结构列表(使用recyclerView实现)
android·gitee
Y多了个想法13 小时前
RK3568 android11 适配敦泰触摸屏 FocalTech-ft5526
android·rk3568·触摸屏·tp·敦泰·focaltech·ft5526
NotesChapter15 小时前
Android吸顶效果,并有着ViewPager左右切换
android
_祝你今天愉快16 小时前
分析android :The binary version of its metadata is 1.8.0, expected version is 1.5.
android
暮志未晚Webgl16 小时前
109. UE5 GAS RPG 实现检查点的存档功能
android·java·ue5
麦田里的守望者江16 小时前
KMP 中的 expect 和 actual 声明
android·ios·kotlin