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最大的不同就是,这里需要自己去写升级脚本,虽然增加了工作量,但是也更加灵活了。

相关推荐
WineMonk14 分钟前
.NET WPF CommunityToolkit.Mvvm框架
.net·wpf·mvvm
Winston Wood2 小时前
Android Parcelable和Serializable的区别与联系
android·序列化
清风徐来辽2 小时前
Android 项目模型配置管理
android
帅得不敢出门2 小时前
Gradle命令编译Android Studio工程项目并签名
android·ide·android studio·gradlew
problc3 小时前
Flutter中文字体设置指南:打造个性化的应用体验
android·javascript·flutter
△曉風殘月〆6 小时前
WPF MVVM入门系列教程(二、依赖属性)
c#·wpf·mvvm
帅得不敢出门13 小时前
安卓设备adb执行AT指令控制电话卡
android·adb·sim卡·at指令·电话卡
我又来搬代码了15 小时前
【Android】使用productFlavors构建多个变体
android
德育处主任16 小时前
Mac和安卓手机互传文件(ADB)
android·macos
芦半山16 小时前
Android“引用们”的底层原理
android·java