Android解决xutils数据库kotlin添加List数组问题

news2024/11/27 0:32:16

Android解决xutils数据库kotlin添加List数组问题

前言:

上一篇我们讲解了xutils中数据库版本升级的使用和问题,这篇博客讲解xutils中数据库添加list数据的问题,这个库真的是很强大,但是数据库的使用真不友好,添加一个list数组的数据居然报错,我的天,没办法,老项目选择了这个库就必须找到解决方法,要是你不想使用此库,可以换一个数据库,比如Room、DataStore、LitePal都是目前不错的选择,我是时间成本不允许,还是不折腾了,后期我会抽时间把这个古老的破旧代码给彻底换掉,要不然不熟悉这个库的人遇到这些坑会折磨死,问题不难,就是要熟悉这个库,能立马定位出问题,拿出解决方法.不扯了,直接上代码.

1.添加数组:

@Table(name = "userinfo")
open class UserInfoDataBaseBean:Serializable{
    @Column(name = "id", isId = true, property = "UNIQUE")
    var id: String? = ""

    @Column(name = "name")
    var name: String? = ""

    @Column(name = "age")
    var age: String? = ""

    @Column(name = "account")
    var account:String ?= ""

    @Column(name = "size")
    var size:String ? = ""

    @Column(name = "avatar")
    var avatar:String ?= ""

    @Column(name = "devices")
    lateinit var devices:MutableList<DevicesInfoBean>
}

在这里插入图片描述

private  val userInfo: UserInfoDataBaseBean by lazy { UserInfoDataBaseBean() }
private lateinit var devicesList: MutableList<DevicesInfoBean>
private var devicesInfoBean = DevicesInfoBean()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    UserInfoDBManager.instance.initDB()
    initData()
}

private fun initData() {
    devicesList = ArrayList()
    devicesInfoBean.deviceName = "客厅空调"
    devicesInfoBean.deviceType = "AIC"
    devicesInfoBean.status = "on"
    devicesInfoBean.address = "01"
    devicesInfoBean.values = "10"
    devicesList.add(devicesInfoBean)
   // userInfo = UserInfoDataBaseBean("1","张帅","18","4","100","", devicesList!!)
}
}

在这里插入图片描述

2.打印日志如下:

新增设备信息列表:
在这里插入图片描述

查询所有信息:
这样操作会导致一个问题,用户信息是查出来了,但是用户信息对象里的devices集合是空的,
在这里插入图片描述

打开数据库表查看数据库信息:发现devices为null,没有存储进去
在这里插入图片描述

3.查找原因:

原因是xutils数据库源码中支持的数据类型只有4种:
所以要使用自定义转换器来转换自定义的数据类型。
在这里插入图片描述

4.解决方法:

自定义转换器来转换自定义的数据类型,xutils内置了一些转换器:

在这里插入图片描述

5.自定义转换器:

xUtils提供了一个转换器的接口ColumnConverter,因些我们只要实现这一接口即可

/**
 *@author: njb
 *@date:  2023/5/27 18:41
 *@desc:
 */
class ListDevicesConverter :ColumnConverter<ListDevices<DevicesInfoBean>>{
    override fun getFieldValue(
        cursor: Cursor,
        index: Int
    ): ListDevices<DevicesInfoBean>? {
        return if(cursor.isNull(index)){
            null
        }else {
            val s = cursor.getString(index)
            val gson = Gson()
            gson.fromJson(
                s,
                object : TypeToken<ListDevices<DevicesInfoBean>>() {}.type
            )
        }
    }

    override fun getColumnDbType(): ColumnDbType {
        return ColumnDbType.TEXT
    }

    override fun fieldValue2DbValue(fieldValue: ListDevices<DevicesInfoBean>?): Any {
       val gson = Gson()
        return gson.toJson(fieldValue)
    }

}

在这里插入图片描述

6.自定义列表数据转换器:

/**
 *@author: njb
 *@date:  2023/5/27 18:42
 *@desc:
 */
class ListDevices <DevicesInfoBean>: ArrayList<DevicesInfoBean>() {

}

在这里插入图片描述

7.注册转换器:

private fun initXUtils() {
    x.Ext.init(this)
    x.Ext.setDebug(true)
    ColumnConverterFactory.registerColumnConverter(ListDevices::class.java,  ListDevicesConverter())
}

在这里插入图片描述

8.具体使用:

@Table(name = "userinfo")
open class UserInfoDataBaseBean:Serializable{
    @Column(name = "id", isId = true, property = "UNIQUE")
    var id: String? = ""

    @Column(name = "name")
    var name: String? = ""

    @Column(name = "age")
    var age: String? = ""

    @Column(name = "account")
    var account:String ?= ""

    @Column(name = "size")
    var size:String ? = ""

    @Column(name = "avatar")
    var avatar:String ?= ""

    @Column(name = "devices")
    lateinit var devices:ListDevices<DevicesInfoBean>
}

在这里插入图片描述

9.测试新增数据:

private  val userInfo: UserInfoDataBaseBean by lazy { UserInfoDataBaseBean() }
private lateinit var devicesList: ListDevices<DevicesInfoBean>
private var devicesInfoBean = DevicesInfoBean()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    UserInfoDBManager.instance.initDB()
    initData()
}

private fun initData() {
    devicesList = ListDevices()
    devicesInfoBean.deviceName = "客厅空调"
    devicesInfoBean.deviceType = "AIC"
    devicesInfoBean.status = "on"
    devicesInfoBean.address = "01"
    devicesInfoBean.values = "10"
    devicesList.add(devicesInfoBean)
   // userInfo = UserInfoDataBaseBean("1","张帅","18","4","100","", devicesList!!)
}

fun add(view: View) {
    try {
        userInfo.let {
            it.id = "1"
            it.name = "张帅"
            it.age = "18"
            it.account = "4"
            it.size = "100"
            it.avatar = ""
            it.devices = devicesList
            UserInfoDBManager.instance.saveUserInfo(it)
            ToastUtils.showShort("添加数据成功" + FireGsonUtil.objectToJson(it))
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

在这里插入图片描述

在这里插入图片描述

10.打印修改后的测试结果:

在这里插入图片描述
在这里插入图片描述

11.查看数据库表新数据:

查询单个信息和所有用户信息都有设备列表数据,可以发现完美解决添加list数组问题,对象和其他类型都是一样的.
在这里插入图片描述

在这里插入图片描述

12.数据修改:

fun update(view: View) {
    try {
        devicesList.clear()
        devicesInfoBean.deviceName = "卧室空调"
        devicesInfoBean.deviceType = "AIC"
        devicesInfoBean.status = "off"
        devicesInfoBean.address = "02"
        devicesInfoBean.values = "06"
        devicesList.add(devicesInfoBean)
        userInfo.run {
            this.id = "22"
            this.name = "李四"
            this.size = "15"
            this.account = "12345"
            this.age = "18"
            this.avatar = ""
            this.devices = devicesList!!
            UserInfoDBManager.instance.updateUserInfo(userInfo)
            LogUtils.d("=更新用户信息===" + FireGsonUtil.objectToJson(userInfo))
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

在这里插入图片描述

13.数据查询:

fun query(view: View) {
    try {
        try {
            val userInfo: UserInfoDataBaseBean? =
                UserInfoDBManager.instance.queryUserInfoByName("张帅")
            LogUtils.d("=查询用户信息===" + FireGsonUtil.objectToJson(userInfo))
        } catch (e: Exception) {
            e.printStackTrace()
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

在这里插入图片描述

14.查询所有数据:

fun queryAll(view: View) {
    try {
        val userList: List<UserInfoDataBaseBean>? = UserInfoDBManager.instance.getAllUserInfo()
        LogUtils.d("=查询所有用户信息===" + FireGsonUtil.listToJson(userList))
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

在这里插入图片描述

15.删除数据:

    fun delete(view: View) {
        try {
            UserInfoDBManager.instance.deleteAllUsers()
            LogUtils.d("=删除后的用户信息===" + UserInfoDBManager.instance.getAllUserInfo())
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

在这里插入图片描述

在这里插入图片描述

16.完整测试代码如下:

package com.example.xutilsdemo

import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.ToastUtils
import com.example.xutilsdemo.db.DevicesInfoBean
import com.example.xutilsdemo.db.ListDevices
import com.example.xutilsdemo.db.UserInfoDBManager
import com.example.xutilsdemo.db.UserInfoDataBaseBean
import com.example.xutilsdemo.utils.FireGsonUtil

class MainActivity : AppCompatActivity() {
    private  val userInfo: UserInfoDataBaseBean by lazy { UserInfoDataBaseBean() }
    private lateinit var devicesList: ListDevices<DevicesInfoBean>
    private val devicesInfoBean by lazy { DevicesInfoBean() }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        UserInfoDBManager.instance.initDB()
        initData()
    }

    private fun initData() {
        devicesList = ListDevices()

       // userInfo = UserInfoDataBaseBean("1","张帅","18","4","100","", devicesList!!)
    }

    fun add(view: View) {
        try {
            devicesInfoBean.deviceName = "客厅空调"
            devicesInfoBean.deviceType = "AIC"
            devicesInfoBean.status = "on"
            devicesInfoBean.address = "01"
            devicesInfoBean.values = "10"
            devicesList.add(devicesInfoBean)
            userInfo.let {
                it.id = "1"
                it.name = "张帅"
                it.age = "18"
                it.account = "4"
                it.size = "100"
                it.avatar = ""
                it.devices = devicesList
                UserInfoDBManager.instance.saveUserInfo(it)
                ToastUtils.showShort("添加数据成功" + FireGsonUtil.objectToJson(it))
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    fun delete(view: View) {
        try {
            UserInfoDBManager.instance.deleteAllUsers()
            LogUtils.d("=删除后的用户信息===" + UserInfoDBManager.instance.getAllUserInfo())
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }


    fun update(view: View) {
        try {
            devicesList.clear()
            devicesInfoBean.deviceName = "卧室空调"
            devicesInfoBean.deviceType = "AIC"
            devicesInfoBean.status = "off"
            devicesInfoBean.address = "02"
            devicesInfoBean.values = "06"
            devicesList.add(devicesInfoBean)
            userInfo.run {
                this.id = "22"
                this.name = "李四"
                this.size = "15"
                this.account = "12345"
                this.age = "18"
                this.avatar = ""
                this.devices = devicesList!!
                UserInfoDBManager.instance.updateUserInfo(userInfo)
                LogUtils.d("=更新用户信息===" + FireGsonUtil.objectToJson(userInfo))
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    fun query(view: View) {
        try {
            try {
                val userInfo: UserInfoDataBaseBean? =
                    UserInfoDBManager.instance.queryUserInfoByName("张帅")
                LogUtils.d("=查询用户信息===" + FireGsonUtil.objectToJson(userInfo))
            } catch (e: Exception) {
                e.printStackTrace()
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    fun queryAll(view: View) {
        try {
            val userList: List<UserInfoDataBaseBean>? = UserInfoDBManager.instance.getAllUserInfo()
            LogUtils.d("=查询所有用户信息===" + FireGsonUtil.listToJson(userList))
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}

17.完整布局代码:

<?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">

    <Button
        android:id="@+id/add"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="add"
        android:text="增加数据"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/delete"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="delete"
        android:text="删除数据"
        app:layout_constraintTop_toBottomOf="@+id/add" />

    <Button
        android:id="@+id/update"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="update"
        android:text="修改数据"
        app:layout_constraintTop_toBottomOf="@+id/delete" />

    <Button
        android:id="@+id/query"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="query"
        android:text="查询数据"
        app:layout_constraintTop_toBottomOf="@+id/update" />

    <Button
        android:id="@+id/query_all"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="queryAll"
        android:text="查询全部数据"
        app:layout_constraintTop_toBottomOf="@+id/query" />
</androidx.constraintlayout.widget.ConstraintLayout>

18.效果预览图:

在这里插入图片描述

19.总结:

以上就是今天的全部内容,从数据库增、删、改、查到数据库添加新数据类型,自定义数据转换器等等,可以说很全面了,基本上涵盖了大部分用法,里面还有根据id和用户名称查询方法,只不过我不想测试了,项目中基本上所有的方法都使用了,如果感兴趣的同学可以自行尝试其他方法,基本上和其他数据库的使用方法没有多大区别,不会有太大问题,遇到问题不要慌,仔细排查,找到原因后努力解决就是了.道险且长,仍需努力,不畏艰难,勇往直前,码完收工,关机睡觉.

20.项目源码地址如下:

https://gitee.com/jackning_admin/xutilsdemo

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

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

相关文章

从零开始手搓一个STM32与机智云的小项目——硬件介绍

文章目录 前言硬件简介选型1.主控2.电源3.电机驱动4.舵机驱动5.USB转TTL6.其他模块 原理图绘制1.STM32最小系统1.电源输入2.晶振选择3.复位电路4.BOOT选择电路5.下载电路 2.电源部分及与PC通信部分3.功能模块的实现1.串口2.定时器输入捕获与输出比较3.硬件SPI4.ADC5.温湿度传感…

学校食堂明厨亮灶 yolov8

学校食堂明厨亮灶可以yolov8网络模型技术&#xff0c;学校食堂明厨亮灶通过对厨师的穿戴情况行为举止等进行监测。YOLOv8 算法的核心特性和改动可以归结为如下&#xff1a;提供了一个全新的 SOTA 模型&#xff0c;包括 P5 640 和 P6 1280 分辨率的目标检测网络和基于 YOLACT 的…

C++环形缓冲区设计与实现:从原理到应用的全方位解析

C环形缓冲区设计与实现&#xff1a;从原理到应用的全方位解析 一、环形缓冲区基础理论解析&#xff08;Basic Theory of Circular Buffer&#xff09;1.1 环形缓冲区的定义与作用&#xff08;Definition and Function of Circular Buffer&#xff09;1.2 环形缓冲区的基本原理&…

SAP-MM-内向外向交货单

1、内向&外向交货单概念 外向交货&#xff08;outbound delivery&#xff09;是用在客户与企业之间的交货单&#xff0c;而内向交货&#xff08;inbound delivery&#xff09;则是用在供应商与企业之间的交货单&#xff1b;换言之&#xff0c;外向交货多用于SD 模块&#…

基于MAX-10 FPGA 超声波测距模块HC_SR04

文章目录 一、介绍超声波测距模块HC_SR04二、模块框图三、模块编写1. 测距信号源2. 距离计算3. 数码管模块4. 顶层模块 四、实验现象总结 一、介绍超声波测距模块HC_SR04 HC-SR04是一种基于超声波的测距模块。该模块向前15度内发送超声波并接收回响&#xff0c;通过发出超声波…

第一章:简单的C程序设计基础

一、C语言词汇 在C语言中使用的词汇分为&#xff1a;关键字、标识符、常量、运算符、分隔符、注释符等。 1.1关键字 1.2标识符 在程序中使用的变量名或函数名等统称为标识符&#xff1b;标识符的命名规则如下&#xff1a; &#xff08;C语言区分大小写&#xff09; 不能是关…

一个简单的基于C/S模型的TCP通信实例

1 TCP协议 1.1 概念 TCP是一种面向连接的、可靠的协议&#xff0c;有点像打电话&#xff0c;双方拿起电话互通身份之后就建立了连接&#xff0c;然后说话就行了&#xff0c;这边说的话那边保证听得到&#xff0c;并且是按说话的顺序听到的&#xff0c;说完话挂机断开连接。也…

2023 华为 Datacom-HCIE 真题题库 08--含解析

单项选择 1.[试题编号&#xff1a;190385] &#xff08;单选题&#xff09;以下关于BGP/MPLSIPVPN路由交互的描述&#xff0c;错误的是哪一项? A、PE与CE之间交互的是IPv4路由信息 B、出口PE可以通过BGP、IGP或静态路由的方式向远端CE发送IPv4路由 C、入口PE将从CE接收到的I…

数组(1)

文章目录 目录1. 一维数组的创建和初始化1.1 一维数组的创建1.2 一维数组的初始化 2. 一维数组的使用3. 一维数组在内存中的存储4. 二维数组的创建和初始化4.1 二维数组的创建4.2 二维数组的初始化 5. 二维数组的使用6. 二维数组在内存中的存储7. 数组越界8. 数组作为函数参数 …

chatgpt赋能python:Python自动填表单:提高工作效率的好帮手

Python 自动填表单&#xff1a;提高工作效率的好帮手 在现代社会中&#xff0c;表单已成为我们日常工作中不可或缺的一部分。填表单虽然看似简单&#xff0c;但是时间一长&#xff0c;不仅会影响工作效率&#xff0c;还会带来心理负担。幸运的是&#xff0c;Python 自动填表单…

Linux-0.11 boot目录bootsect.s详解

Linux-0.11 boot目录bootsect.s详解 模块简介 bootsect.s是磁盘启动的引导程序&#xff0c;其概括起来就是代码的搬运工&#xff0c;将代码搬到合适的位置。下图是对搬运过程的概括&#xff0c;可以有个印象&#xff0c;后面将详细讲解。 bootsect.s主要做了如下的三件事: 搬…

doris---Rollup

Rollup 3.5.1基本概念 通过建表语句创建出来的表称为 Base 表&#xff08;Base Table,基表&#xff09; 在 Base 表之上&#xff0c;我们可以创建任意多个 ROLLUP 表。这些 ROLLUP 的数据是基于 Base 表产生的&#xff0c;并且在物理上是独立存储的。 Rollup表的好处&#xff…

C#调用FreeSpire.PDF获取PDF文档中使用的字体

除了图片之外&#xff0c;电子文件中使用的字体都必须要在本机中安装才能正常查看文字&#xff08;word缺少字体的话会自动使用相似或默认字体&#xff09;&#xff0c;要想知道电子文件中使用的字体&#xff0c;可以将电子文件转换为PDF文件&#xff08;如果是打印成PDF的话&a…

chatgpt赋能python:Python收集数据在SEO中的重要性

Python 收集数据在 SEO 中的重要性 随着互联网的发展&#xff0c;搜索引擎对于用户获取信息的重要性日益增加。SEO&#xff08;搜索引擎优化&#xff09;一直是每个网站必须考虑的问题。Python 收集数据在 SEO 中可以发挥重要的作用&#xff0c;帮助网站提高排名。下面我们来详…

Solidity拓展:数学运算过程中数据长度溢出的问题

在数学运算过程中假如超过了长度则值会变成该类型的最小值&#xff0c;如果小于了该长度则变成最大值 数据上溢 uint8 numA 255; numA;uint8的定义域为[0,255]&#xff0c;现在numA已经到顶了&#xff0c;numA会使num变成0(由于256已经超过定义域&#xff0c;它会越过256&…

结构体 --- C语言

目录 1.结构体的声明 2.结构体变量的定义和初始化 3.结构体成员访问 4.结构体传参 1.结构体的声明 结构是一些值的集合&#xff0c;这些称为成员变量&#xff0c;结构的每个成员可以是不同类型的变量。 而数组是一组类型相同的元素的集合。 生活中的描述 人&#xff1a;名…

测试C#分词工具jieba.NET(续1:提取关键词及并行分词)

jieba.NET支持通过两种算法提取文本关键词&#xff1a;TF-IDF算法和TextRank算法&#xff0c;关于这两种算法的介绍详见参考文献10-11&#xff0c;在jieba.NET中对应的类为TfidfExtractor和TextRankExtractor&#xff0c;这两个分词都都支持调用ExtractTags和ExtractTagsWithWe…

文件上传至公有云Nos及对接CDN

项目开发中&#xff0c;需要将图片文件上传至网易公有云的Nos,并且结合CDN做加速服务&#xff0c;记录一下开发过程。流程图&#xff1a; 1. 文件上传到公有云Nos 网易对象存储服务&#xff08;Netease Object Storage&#xff0c;简称NOS&#xff09;是网易数帆提供的高可用…

pycharm环境下打开Django内置的数据库Sqlite出错问题解决

问题描述 在数据库库文件中写入一条记录后&#xff0c;在pycharm的terminal终端下执行查看表的命令出错 执行语句为&#xff1a; 连接数据库报错 python manage.py dbshell CommandError: You appear not to have the sqlite3 program installed or on your path. Error:…

JavaScript之DOM基础

1. 初识DOM DOM: 文档对象模型 是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。 w3c已经定义了一系列的DOM接口&#xff0c;通过这些DOM接口可以改变网页的内容&#xff0c;结构和样式。 DOM树&#xff1a;文档&#xff1a;一个页面就是一个文档, DOM中使用d…