Room+ViewModel+LiveData

news2024/11/26 22:47:44

Room框架支持的LiveData会自动监听数据库的变化,当数据库发生变化的时候,会调用onChanged函数更新UI 

1.MainActivity

package com.tiger.room2;

import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
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 StudentRecyclerViewAdapter adapter;
    private StudentViewModel studentViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        RecyclerView recycleView = findViewById(R.id.recycleView);
        recycleView.setLayoutManager(new LinearLayoutManager(this));
        List<Student> students = new ArrayList<>();
        adapter = new StudentRecyclerViewAdapter(students);
        recycleView.setAdapter(adapter);
        studentViewModel = new ViewModelProvider(this).get(StudentViewModel.class);
        //自动更新,给LiveData 添加监听
        LiveData<List<Student>> listLiveData = studentViewModel.queryAllStudentsLive();
        List<Student> value = listLiveData.getValue();
        if (value==null) {
            Log.d("ning","value is null");
        }else {
            Log.d("ning",value.toString());
        }

        listLiveData.observe(this, new Observer<List<Student>>() {
            @Override
            public void onChanged(List<Student> students) {
                Log.d("ning",listLiveData.getValue().toString());
                adapter.setStudents(students);
                adapter.notifyDataSetChanged();
            }
        });
    }

    public void mInsert(View view) {
        Student jack = new Student("Jack", 20);
        Student rose = new Student("rose", 23);
        studentViewModel.insertStudent(jack, rose);
    }

    public void mDelete(View view) {
        Student student = new Student(1);
        studentViewModel.deleteStudent(student);
    }

    public void mUpdate(View view) {
        Student rose = new Student(3, "wqeqasdaddqweqwe", 212313);
        studentViewModel.updateStudent(rose);
    }

    public void mClear(View view) {
        studentViewModel.deleteAllStudent();
    }

}

2.MyDataBase

package com.tiger.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;


    public static MyDataBase getInstance(Context context){

        if (mInstance == null){
            synchronized(MyDataBase.class){
                if (mInstance == null){
                    mInstance = Room.databaseBuilder(context.getApplicationContext(), MyDataBase.class,DATABASE_NAME)
//                            .allowMainThreadQueries() 允许主线程操作数据库
                            .build();
                }
            }

        }
        return mInstance;
    }

    public abstract StudentDao getStudentDao();//room自动实现

}

3.Student

package com.tiger.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;


//    @Ignore
//    public boolean flag; 属性也可以忽略 ,代表它不是数据库的一列

    public Student(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    @Ignore //room忽略此构造方法 构造对象
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Ignore
    public Student(int id) {
        this.id = id;
    }


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

4.StudentDao

package com.tiger.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 {

    @Insert
    void insert(Student... students);

    @Delete
    void deleteStudent(Student... students);

    @Query("delete from student")
    void deleteAll();

    @Update
    void updateStudent(Student... students);

    @Query("select * from student")
    LiveData<List<Student>> getAllStudentsLive();


    @Query("select * from student where id = :id")
    Student getStudentById(int id);


}

5.StudentRecyclerViewAdapter

package com.tiger.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;

/**
 * @author ningchuanqi
 * @version V1.0
 */
public class StudentRecyclerViewAdapter extends RecyclerView.Adapter {

    List<Student> students;

    public StudentRecyclerViewAdapter(List<Student> students) {
        this.students = students;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
       View root = LayoutInflater.from(parent.getContext()).inflate(R.layout.item,parent,false);
       return new MyViewHoder(root);
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        Student student = students.get(position);
        TextView tvId = holder.itemView.findViewById(R.id.tvId);
        tvId.setText(String.valueOf(student.id));

        TextView tvName = holder.itemView.findViewById(R.id.tvName);
        tvName.setText(student.name);

        TextView tvAge = holder.itemView.findViewById(R.id.tvAge);
        tvAge.setText(String.valueOf(student.age));
    }

    @Override
    public int getItemCount() {
        return students.size();
    }

    static class MyViewHoder extends RecyclerView.ViewHolder {

        public MyViewHoder(@NonNull View itemView) {
            super(itemView);
        }
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }
}

6.StudentReposity

package com.tiger.room2;

import android.content.Context;
import android.os.AsyncTask;
import android.view.View;

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


    public void insertStudent(Student ... students) {
        new InsertStudentTask(studentDao).execute(students);
    }


    class InsertStudentTask extends AsyncTask<Student, Void, Void> {

        private StudentDao studentDao;

        public InsertStudentTask(StudentDao studentDao) {
            this.studentDao = studentDao;
        }

        @Override
        protected Void doInBackground(Student ... students) {
            studentDao.insert(students);
            return null;
        }
    }


    public void updateStudent(Student... students) {
        new UpdateStudentTask(studentDao).execute(students);
    }

    class UpdateStudentTask extends AsyncTask<Student, Void, Void> {

        private StudentDao studentDao;

        public UpdateStudentTask(StudentDao studentDao) {
            this.studentDao = studentDao;
        }

        @Override
        protected Void doInBackground(Student... students) {
            studentDao.updateStudent(students);
            return null;
        }
    }

//除非服务器崩了,要不然代码不可能错

    public void deleteStudent(Student ... student) {
        new DeleteStudentTask(studentDao).execute(student);
    }

    class DeleteStudentTask extends AsyncTask<Student, Void, Void> {

        private StudentDao studentDao;

        public DeleteStudentTask(StudentDao studentDao) {
            this.studentDao = studentDao;
        }

        @Override
        protected Void doInBackground(Student... students) {
            studentDao.deleteStudent(students);
            return null;
        }
    }

    public void deleteAllStudent() {
        new DeleteAllStudentTask(studentDao).execute();
    }

    class DeleteAllStudentTask extends AsyncTask<Void, Void, Void> {

        private StudentDao studentDao;

        public DeleteAllStudentTask(StudentDao studentDao) {
            this.studentDao = studentDao;
        }


        @Override
        protected Void doInBackground(Void... voids) {
            studentDao.deleteAll();
            return null;
        }
    }

    public LiveData<List<Student>> queryAllStudentsLive() {
        return studentDao.getAllStudentsLive();
    }

//    class GetAllStudentTask extends AsyncTask<Void,Void,Void>{
//
//        private StudentDao studentDao;
//
//        public GetAllStudentTask(StudentDao studentDao) {
//            this.studentDao = studentDao;
//        }
//
//        @Override
//        protected Void doInBackground(Void... voids) {
//            List<Student> students = studentDao.getAllStudent();
//            adapter.setStudents(students);
//            return null;
//        }
//
//        @Override
//        protected void onPostExecute(Void aVoid) {
//            super.onPostExecute(aVoid);
//            adapter.notifyDataSetChanged();
//        }
//    }


}

7.StudentViewModel

package com.tiger.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 studentRepository;

    public StudentViewModel(@NonNull Application application) {
        super(application);
        this.studentRepository = new StudentRepository(application);
    }

    public void insertStudent(Student ... students){
        studentRepository.insertStudent(students);
    }
    public void deleteStudent(Student ... students){
        studentRepository.deleteStudent(students);
    }
    public void updateStudent(Student ... students){
        studentRepository.updateStudent(students);
    }

    public void deleteAllStudent(){
        studentRepository.deleteAllStudent();
    }

    public LiveData<List<Student>>  queryAllStudentsLive(){
        return studentRepository.queryAllStudentsLive();
    }

}

8.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.Guideline
        android: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.Guideline
        android:id="@+id/guideline4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.5" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.1" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycleView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.709"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/guideline3" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="增加"
        android:onClick="mInsert"
        app:layout_constraintBottom_toTopOf="@+id/guideline5"
        app:layout_constraintEnd_toStartOf="@+id/guideline4"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="删除"
        android:onClick="mDelete"
        app:layout_constraintBottom_toTopOf="@+id/guideline5"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/guideline4"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="修改"
        android:onClick="mUpdate"
        app:layout_constraintBottom_toTopOf="@+id/guideline3"
        app:layout_constraintEnd_toStartOf="@+id/guideline4"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/guideline5" />

    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="清空"
        android:onClick="mClear"
        app:layout_constraintBottom_toTopOf="@+id/guideline3"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/guideline4"
        app:layout_constraintTop_toTopOf="@+id/guideline5" />
</androidx.constraintlayout.widget.ConstraintLayout>

9.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"
    android:paddingVertical="10dip">

    <TextView
        android:id="@+id/tvId"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView"
        tools:text="1"
        android:textSize="18sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/guideline"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tvName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView"
        tools:text="Jack"
        android:textSize="18sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/guideline2"
        app:layout_constraintStart_toStartOf="@+id/guideline"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tvAge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView"
        tools:text="18"
        android:textSize="18sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/guideline2"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.8" />

    <androidx.constraintlayout.widget.Guideline
        android: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.ConstraintLayout>

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

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

相关文章

Vue3全家桶 - Pinia - 【1】(安装与使用 + Store + State + Getters + Actions)

Pinia pinia 是 Vue 的专属状态管理库&#xff0c;它允许你跨组件或跨页面共享状态&#xff1b; 一、 安装与使用 pinia 安装语法&#xff1a;yarn add pinia npm install pinia创建一个 pinia &#xff08;根存储&#xff09;并将其传递给应用程序&#xff1a; 目标文件&am…

[C语言] 数据存储

类型意义&#xff1a; 1.类型决定内存空间大小&#xff08;大小决定了使用范围&#xff09; 2.如何看待内存空间的视角 类型分类 整形 类型大小(字节)short2int4long4long8 浮点型 类型大小(字节)float4double8long double12 构造类型 数组结构性struct联合union枚举enum 指…

七个项目掌握freertos

1、闪烁LED&#xff1a; 最基本的示例项目&#xff0c;涉及到创建一个简单的任务&#xff0c;用于控制LED的闪烁。这个项目会教你如何初始化FreeRTOS并创建任务。 #include "FreeRTOS.h" #include "task.h" #define LED_PIN (某个GPIO引脚)void vBlinkTas…

BUGKU-WEB cookies

题目描述 题目截图如下&#xff1a; 进入场景看看&#xff1a; 解题思路 看源码看F12&#xff1a;看请求链接看提示&#xff1a;cookies欺骗 相关工具 插件&#xff1a;ModHeader或者hackbarbase64解密 解题步骤 看源码 就是rfrgrggggggoaihegfdiofi48ty598whrefeoia…

2000-2023年7月全国各省专利侵权结案案件数量数据

2000-2023年7月全国各省专利侵权结案案件数量数据 1、时间&#xff1a;2000-2023年7月 2、指标&#xff1a;地区、年份、专利侵权纠纷行政案件-结案数目 3、范围&#xff1a;31省 4、来源&#xff1a;国家知识产权局&#xff0c;并由该局每个月公布的数据汇总而成 5、指标…

STM32CubeIDE基础学习-STM32CubeIDE软件代码编写格式问题

STM32CubeIDE基础学习-STM32CubeIDE软件代码编写格式问题 前言 代码编写最好就是规定一个格式&#xff0c;或者建立一个偏好&#xff0c;这样写出来的代码就方便自己管理了&#xff0c;不然代码乱放下次打开工程就很难找到具体位置&#xff0c;如果规定了格式&#xff0c;那么…

LeetCode中的returnSize和returnColumnSize

今天这篇比较水&#xff0c;不过本文要讲的内容是我曾经遇到过的问题&#xff0c;也可能是大部分人在初次接触力扣时的一些疑问。当时遇到这个问题也是上网找了许久没有找到满意的答案&#xff0c;现在自己明白了&#xff0c;也希望能够帮助还抱有疑惑的各位解答。 如果我说的…

认证授权与JWT

认证授权与JWT 1、认证授权概念介绍1.1 什么是认证1.2 什么是授权 2、权限数据模型3、RBAC权限模型3.1 介绍3.2 基于角色访问控制3.3 基于资源访问控制 4、常见认证方式4.1 Cookie-Session4.2 jwt令牌无状态认证 5 常见技术实现6.Jwt介绍6.1 JWT简介6.2.Jwt组成 7、JWT使用7.1 …

2024-3-12尾盘一致转分歧

安彩高科开一字符合预期&#xff0c;昨天风光储锂电大涨&#xff0c;理应给大溢价&#xff0c;超预期是 艾艾精工 高开秒板&#xff0c;立航科技高开分歧反核承接良好回封一致&#xff0c;带动了低空经济板块高潮&#xff0c;低空经济开始往 碳纤维 方向扩散。盘中我说了 三晖…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的火焰检测系统(Python+PySide6界面+训练代码)

摘要&#xff1a;本研究详述了一种采用深度学习技术的火焰检测系统&#xff0c;该系统集成了最新的YOLOv8算法&#xff0c;并与YOLOv7、YOLOv6、YOLOv5等早期算法进行了性能评估对比。该系统能够在各种媒介——包括图像、视频文件、实时视频流及批量文件中——准确地识别火焰目…

蓝桥杯真题讲解:子矩阵(二维滑动窗口)

蓝桥杯真题讲解&#xff1a;子矩阵&#xff08;二维滑动窗口&#xff09; 一、视频讲解二、正解代码 一、视频讲解 蓝桥杯真题讲解&#xff1a;子矩阵&#xff08;二维滑动窗口&#xff09; 二、正解代码 //二维单调队列 #include<bits/stdc.h> #define endl \n #def…

Midjourney绘图欣赏系列(十一)

Midjourney介绍 Midjourney 是生成式人工智能的一个很好的例子&#xff0c;它根据文本提示创建图像。它与 Dall-E 和 Stable Diffusion 一起成为最流行的 AI 艺术创作工具之一。与竞争对手不同&#xff0c;Midjourney 是自筹资金且闭源的&#xff0c;因此确切了解其幕后内容尚不…

(二)运行自己的stable-diffusion

前面的步骤如https://datawhaler.feishu.cn/docx/BwjzdQPJRonFh8xeiSOcRUI3n8b所示 拷贝、解压文件后&#xff0c;进入到stable-diffusion-webui的文件夹中&#xff0c;文件如下&#xff1a; 启动&#xff1a; 运行效果&#xff1a; 由于生成了好几个图&#xff0c;所以…

布隆过滤器(做筛选器索引)

什么是布隆过滤器 布隆过滤器&#xff08;Bloom Filter&#xff09;是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。 它的优点是空间效率和查询时间都比一般的算法要好的多&#xff0c;缺点是…

学习vue3第四节(ref以及ref相关api)

主要记录以下api&#xff1a;ref()、isRef()、unref()、 shallowRef()、triggerRef()、customRef() 1、ref() 定义 接受一个内部值&#xff0c;返回一个响应式的、可更改的 ref 对象&#xff0c;此对象只有一个指向其内部值的属性 .value&#xff0c;.value属性用于追踪并且存…

I2C驱动AT24C02

文章目录 一、硬件电路设备地址 二、使用步骤字节写:页写入:任意写:任意读: 一、硬件电路 设备地址 设备需要一个8位的设备地址字&#xff0c;后面跟着一个启动条件&#xff0c;以使芯片能够进行读或写操作 设备地址字由一个强制的1,0序列的前四个最有效的位&#xff0c;如所示…

简单使用国产数据库—达梦

达梦数据库是一款由中国的达梦软件公司开发的关系数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它在业界以其高性能、可扩展性和安全性而著称。该系统广泛应用于各种应用程序的数据存储和管理&#xff0c;满足用户对于数据处理和管理的多样化需求。 安装好的达梦数…

容联云孙昌勋:聚焦“营销服”数智化转型,构筑金融业增长引擎

在每日经济新闻2024全国两会特别报道中&#xff0c;容联云创始人兼CEO孙昌勋针对“人工智能”在具体行业如何开展时表示&#xff1a;“随着泛金融行业用户渠道与体验发生变化&#xff0c;金融业对营销、销售、服务等场景的数智化改造有巨大的需求&#xff0c;人工智能等科技投入…

Qt/QML编程之路:openglwidget和倒车影像的切换(43)

关于如何实现一个基于OpenGL的3d 图形,这个有很多专门的介绍,我在开发中遇到了这么一个问题: 如何实现一个倒车影像的video显示与一个3D物体显示的切换,因为开窗在同样的一个位置,如果车子倒车启动,则需要将原本显示3D的地方切换为视频图像的显示。 class testOpenGl : …

docker容器镜像管理+compose容器编排(持续更新中)

目录 一、 Docker的基本组成 二、 容器和镜像的关系 2.1 面向对象角度 2.2 从镜像容器角度 三、 容器命令 3.1 使用Ubuntu 3.1.1 下载镜像 3.1.2 新建和启动容器 run 3.1.3交互式 compose编排与部署 1. docker-compose部署 2. docker-compose.yml模板 …