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

news2024/11/18 8:47:13

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

一,基本使用

关于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包装的集合:

@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修改为单例模式:

@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使用:

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:

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:

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 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 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,使用:

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()

@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:

@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中增加升级功能:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1309171.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Axure RP9】元件应用(图文并茂)----含登入,个人简历案例

目录 : 一&#xff0c;元件基本介绍 1.1 元件概述 1.2 元件操作 1.3 快捷键大全 二&#xff0c;基本元件的应用 2.1 形状 2.2 图片 2.3 文本 2.4 线段原件 2.5 热区 2.5.1 热区应用 三, 表单型元件的应用 3.1 文本框 3.2 文本域 3.3 下拉列表 3.4 列表框 3.5 …

mysql EXPLAIN命令的输出列简介

MySQL :: MySQL 8.2 Reference Manual :: 8.8.2 EXPLAIN Output Format explain命令提供了mysql数据库如何执行SQL语句的信息&#xff0c;可以跟 SELECT, DELETE, INSERT, REPLACE, UPDATE, 和 TABLE一起使用。 explain命令可能输出多行&#xff0c;每行涉及一个表 。 先来看…

嵌入式工程师是否需要学历和基础?

今日话题&#xff1a;嵌入式工程师是否需要学历和基础&#xff1f;想要成为一位真正独当一面的嵌入式工程师&#xff0c;不一定需要特定的学历和基础&#xff0c;但需要耐心和时间。通常&#xff0c;至少需要五年的坚定学习和实践。这个过程中&#xff0c;你将面临各种挑战&…

Linux CentOS7 Docker安装Jenkins

1 sudo yum update #确保yum包更新到最新 service network restart #重启网络 2、查询镜像 docker search jenkins 3、拉取镜像 docker pull jenkins/jenkins #拉取镜像 4、创建Jenkins工作目录&#xff0c;并将容器内目录挂载到此目录…

人工智能中的顺序学习:概念、应用和未来方向

一、介绍 人工智能 &#xff08;AI&#xff09; 中的顺序学习是一个关键研究领域&#xff0c;近年来引起了人们的极大兴趣。它指的是人工智能系统从数据序列中学习的能力&#xff0c;其中数据点的顺序至关重要。本文将探讨人工智能中顺序学习的概念、其重要性、应用、方法、挑战…

数字化管理系统:引领企业智能化时代

随着数字化和智能化的风潮席卷而来&#xff0c;企业数字化管理系统成为提升竞争力、提高效率的不可或缺的工具。在服装管理系统、仓储管理系统等方面应用的RFID技术和数字大屏更是为企业带来了前所未有的便利和优势。 数字化管理系统的重要性&#xff1a; 数字化管理系统是企…

CNS0创建交货单没有WBS元素

1、问题 CNS0创建交货单带不出WBS&#xff0c;但是交货单过账之后&#xff0c;又可以读取到WBS。 2、原因 2.1、项目挂料 创建项目挂料时&#xff0c;当物料为通用料&#xff0c;则在网络中挂料时&#xff0c;采购类型为网络预留 当物料为专用料&#xff0c;则在网络中挂料时…

linux中的od命令与hexdump命令

初步解读两个命令 在Linux中&#xff0c;"od"和"hexdump"命令都用于以十六进制和其他格式显示文件的内容。它们提供了对文件进行二进制查看和分析的功能。以下是它们的简要说明&#xff1a; od命令&#xff1a; “od”&#xff08;octal dump&#xff09;…

在javaweb项目中resource目录和webapp目录的区别

resource存放的是一些配置文件&#xff0c;这些文件一般都是与java代码相关的配置文件&#xff0c;比如这里的jdbc配置文件,在java中可以使用这个目录下的文件&#xff0c;不用写全路径 webapp存放的是web的资源文件&#xff0c;如jsp,html,css&#xff0c;js文件,在网页请求会…

并发编程-线程等待唤醒机制

目录 前言 ​编辑 线程等待和唤醒的方法 wait() 方法&#xff1a; notify() 方法&#xff1a; 注意事项和建议&#xff1a; 我的其他博客 前言 程等待唤醒机制是多线程编程中用于线程之间协调和通信的一种机制。在多线程环境中&#xff0c;有时候一个线程需要等待某个条件…

ResourceSat2卫星数据下载

印度5米遥感卫星数据开放下载 简介 印度国家遥感中心( NRSC )于近期开放了ResourceSat2卫星的LISS4传感器的数据下载权限&#xff0c;最高分辨率为5米。此次可供下载的有3个波段&#xff08;近红外/红/绿&#xff09;&#xff0c;下载附带3个GeoTIFF和一个元数据文件&#xf…

OpenCV极坐标变换函数warpPolar的使用

学更好的别人&#xff0c; 做更好的自己。 ——《微卡智享》 本文长度为1702字&#xff0c;预计阅读4分钟 前言 前阵子在做方案时&#xff0c;得了几张骨钉的图片&#xff0c;骨科耗材批号效期管理一直是比较麻烦的&#xff0c;贴RFID标签成本太高&#xff0c;所以一般考虑还是…

大数据技术之Hive(超级详细)

第1章 Hive入门 1.1 什么是Hive Hive&#xff1a;由Facebook开源用于解决海量结构化日志的数据统计。 Hive是基于Hadoop的一个数据仓库工具&#xff0c;可以将结构化的数据文件映射为一张表&#xff0c;并提供类SQL查询功能。 本质是&#xff1a;将HQL转化成MapReduce程序 …

微信小程序使用camera扫码获取相机权限

确保用户隐私指引已经明确使用相机功能 “mp-weixin”: "permission": {"scope.camera": {"desc": "需要使用相机功能&#xff0c;请授权"}}wx.authorize({scope: scope.camera,success(res) {console.log(res, 用户成功授权)// 用户…

在Node.js中MongoDB插入数据的方法

本文主要介绍在Node.js中MongoDB插入数据的方法。 目录 Node.js中MongoDB插入数据使用MongoDB原生驱动插入数据使用Mongoose插入数据 Node.js中MongoDB插入数据 在Node.js中&#xff0c;可以使用MongoDB原生驱动或Mongoose库来连接和操作MongoDB数据库。 以下是在Node.js中使用…

【洛谷算法题】P1422-小玉家的电费【入门2分支结构】

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P1422-小玉家的电费【入门2分支结构】&#x1f30f;题目描述&#x1f30f;输入格…

医学检验系统LIS源码,C# +.Net+Oracle

LIS是HIS的一个组成部分&#xff0c;通过与HIS的无缝连接可以共享HIS中的信息资源&#xff0c;使检验科能与门诊部、住院部、财务科和临床科室等全院各部门之间协同工作。  体系结构&#xff1a;Client/Server架构 客户端&#xff1a;WPFWindows Forms 服务端&#xff1a;C…

【网络安全】Suspicious DNS Query(可疑的DNS查询)

文章目录 名词解释可能原因分析Action sinkhole在防火墙里面查询Suspicious DNS Query预防Suspicious DNS查询带来的风险推荐阅读 名词解释 “Suspicious DNS Query&#xff08;可疑的DNS查询&#xff09;”通常指的是在网络中检测到的可能具有风险或异常行为的DNS&#xff08…

在国内,现在月薪1万是什么水平?

看到网友发帖问&#xff1a;现在月薪1W是什么水平&#xff1f; 在现如今的情况下&#xff0c;似乎月薪过万这个标准已经成为衡量个人能力的一个标准了&#xff0c;尤其是现在互联网横行的时代&#xff0c;好像年入百万&#xff0c;年入千万就应该是属于大众的平均水平。 我不是…

电子秤ADC芯片CS1237技术资料问题合集

问题11&#xff1a;实际应用中&#xff0c;多个称重传感器应该怎么与ADC连接&#xff1f; 解答&#xff1a;如果传感器是测量同一物体&#xff08;例如&#xff1a;厨房垃圾处理器&#xff09;&#xff0c;一般建议使用并联的方式。则相同类型的信号线连接在一起。对于传感器的…