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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

谷歌上架应用的机审流程或审核机制是怎么样的?

Google play是全球最大安卓应用市场&#xff0c;拥有巨大的流量&#xff0c;是开发者们上架应用的首选平台。不过&#xff0c;开发者们的应用需要经过谷歌严格审核&#xff0c;确保符合谷歌应用相关政策和法律法规才能成功上架。 众所周知&#xff0c;谷歌审核系统&#xff0c…

基于ssm民宿管理系统论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本民宿管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&am…

c语言结构体调用格式与对齐

1.声明形式&#xff1a; struct 结构体名字 { 结构体成员 }结构体变量名&#xff1b; 2.赋值方法 3.结构体对齐&#xff1a; 1.起始偏移量&#xff1a;默认结构体第一个元素对齐0起始偏移量&#xff0c;第一个元素占一个字节&#xff0c;此时偏移量为1. 2.标准数&#xff…

基于stm32 FP-AUD-SMARTMIC1 音频系统开发

基于stm32 FP-AUD-SMARTMIC1 音频系统开发 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务,+群赠送语音信号处理降噪算法,蓝牙耳机音频,DSP音频项目核心开发资料, FP-AUD-SMARTMIC1 是一个用于 STM32F4Discovery …

Tcl语言语法精炼总结

一、置换符号 1.变量置换 $ TCl解释器会将认为$后面为变量名&#xff0c;将变量名置换成它的值 2.命令置换 [] []内是一个独立的TCL语句 3.反斜杠置换 \ 换行符、空格、[、$等被TCL解释器当作特殊符号处理。加上反斜杠后变成普通字符 \t TAB \n 换行符 4.双引号 “” “…

spring国际化 - i18n

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 本…

[LCTF 2018]bestphp‘s revenge

文章目录 前置知识call_user_func()函数session反序列化PHP原生类SoapClient 解题步骤 前置知识 call_user_func()函数 把第一个参数作为回调函数调用 eg:通过函数的方式回调 <?php function barber($type){echo "you wanted a $type haircut, no problem\n";}c…

20231213给Ubuntu18.04.6LTS新加一块HDD机械硬盘

20231213给Ubuntu18.04.6LTS新加一块HDD机械硬盘 2023/12/13 22:50 rootrootrootroot-X99-Turbo:~$ cat /etc/issue Ubuntu 18.04.6 LTS \n \l sudo fdisk -l rootrootrootroot-X99-Turbo:~$ rootrootrootroot-X99-Turbo:~$ sudo fdisk -lu Disk /dev/sda: 2.7 TiB, 300059298…

Nginx.conf核⼼配置⽂件解读

Nginx的核⼼配置⽂件conf/nginx.conf包含三块内容&#xff1a;全局块、events块、http块 全局块 从配置⽂件开始到events块之间的内容&#xff0c;此处的配置影响nginx服务器整体的运⾏&#xff0c;⽐如worker进程的数量、错误⽇志的位置等。 运行用户是指操作nginx的用户意…

改进YOLOv8注意力系列二:结合CBAM、Coordinate Attention、deformable_LKA_Attention可变形大核注意力

改进YOLOv8注意力系列二:结合ACmix、Biformer、BAM注意力机制 代码CBAM注意力Coordinate Attention坐标注意力deformable_LKA_Attention可变形大核注意力加入方法各种yaml加入结构本文提供了改进 YOLOv8注意力系列包含不同的注意力机制以及多种加入方式,在本文中具有完整的代…

前端反向代理的神奇世界:加速、安全与缓存的秘密(下)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

V友故事·感恩节特辑|Vol.7 用 EasyV 开启不受限的可视化设计体验

本期嘉宾 张啸天&#xff08;站酷 ID&#xff1a;张张张夏天&#xff09;&#xff0c;从事设计行业已经 4 年多&#xff0c;接触可视化设计工作大概有 2 年时间。目前就职于卓见云的可视化业务部门&#xff0c;所在团队大概 15 人左右&#xff0c;包含了产品、设计、开发、引擎…

PCL点云处理之判断某一点在三角形的内部、外部、还是边上(二百二十二)

PCL点云处理之判断某一点在三角形的内部、外部、还是边上(二百二十二) 一、算法介绍二、算法实现1.代码2.结果一、算法介绍 点与三角形的位置共有三种: 1 内部 2 外部 3 点刚好在边上 (这个判断还是很有必要的,应用广泛,下面代码复制粘贴即可使用,纯C++实现) 二、算…

高效编程“武功秘笈”,手把手教你写一波!

随着今年人工智能技术的大火&#xff0c;越来越多的领域正在接受和利用这项强大的 AI 科技&#xff0c;以实现更高效、更智能的工作方式。在软件开发领域&#xff0c;AI 技术更是为我们的工作带来了前所未有的变革。从自动代码生成到智能编程助手&#xff0c;AI 正在逐步改变开…

鸿蒙(HarmonyOS)北向开发项目编译问题汇总

运行Hello World Hello World 工程可以运行在模拟器中&#xff0c;或者运行在真机设备中。本示例先以选择将 Hello World 工程运行在模拟器中进行说明&#xff0c;如果选择运行在真机设备中&#xff0c;需要先对工程进行签名&#xff0c;然后才能运行在真机设备中。 DevEco S…

Ubuntu 22安装PHP环境

参考博客为《练习 0&#xff08;2/2&#xff09;&#xff1a;Ubuntu 环境下安装PHP&#xff08;PHP-FPM&#xff09;》和《原生态Ubuntu部署LAMP环境 PHP8.1MySQLApache》 sudo apt-get install -y php7.4想要安装php7.4&#xff0c;发现安装的是php8.1。 完成如下图&#xf…

自控基础理论篇-品质因数与阻尼系数的关系

1.二阶低通滤波系数的标准形式 &#xff08;a&#xff09;与阻尼系数相关的标准形式 &#xff08;b&#xff09;与品质因数相关的标准形式 比较上式可以分析得到,当A0等于1的时候&#xff0c;阻尼比与品质因素有一个对应关系 2.二阶带通滤波系数的标准形式 &#xff08;a&…

JVM虚拟机系统性学习-对象的创建流程及对象的访问定位

对象的创建流程与内存分配 对象创建流程如下&#xff1a; Java 中新创建的对象如何分配空间呢&#xff1f; new 的对象先放 Eden 区&#xff08;如果是大对象&#xff0c;直接放入老年代&#xff09;当 Eden 区满了之后&#xff0c;程序还需要创建对象&#xff0c;则垃圾回收…

掌握Selenium中元素缓存技巧,提高测试效率!

一、前言 / INTRODUCTION 本篇文章我们再来看下如何在Selenium中使用缓存 页面对象模型是UI自动化测试中的一种很好的设计模式&#xff0c;我们使用FindBy和FindAll注释来标记Page Object中的WebElement。 本次要讲的CacheLookup是一个非常重要但被忽视的注释&#xff0c;它可…

Linux查看端口使用情况

1、netstat命令 netstat命令用于显示与网络相关的信息&#xff0c;包括正在使用的端口。 netstat -tuln 其中&#xff0c;-t选项表示显示TCP连接&#xff0c;-u选项表示显示UDP连接&#xff0c;-l选项表示仅显示监听状态的连接&#xff0c;-n选项表示显示数字格式的IP地址和端口…