Kotlin中使用Java数据类时引发的一个Bug

文章目录

      • 基础复习:Kotlin语言中的对象比较
      • 背景
      • 问题出现
      • 解决方式
        • 方式一
        • 方式二

基础复习:Kotlin语言中的对象比较

  • 比较对象的内容是否相等 (== 或者 equals )Kotlin 中的操作符 == 和 equals效果相同 ,都用于比较对象的内容是否相等, Kotlin中建议直接使用 ==
  • 比较对象的引用是否相等 ( === )Kotlin 中的操作符 === 用于比较对象的引用是否指向同一个地址,运行时如果是基本数据类型 === 等价于 ==

背景

如图效果,通过RecyclerView实现,每次通过对每个Item前后数据进行对比来确定执行什么操作(如Item的insert、update、delete等),这里使用RecyclerView库中的DiffUtil.Callback()来进行的前后数据对比,如下示例:

class DataDiffUtil(private val oldModels: List<Any>, private val newModels: List<Any>) :DiffUtil.Callback() {/*** 旧数据*/override fun getOldListSize(): Int = oldModels.size/*** 新数据*/override fun getNewListSize(): Int = newModels.size/*** DiffUtil调用来决定两个对象是否代表相同的Item。true表示两个Item相同(表示View可以复用),false表示不相同(View不可以复用)* 例如,如果你的项目有唯一的id,这个方法应该检查它们的id是否相等。*/override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {return oldModels[oldItemPosition]::class.java == newModels[newItemPosition]::class.java}/*** 比较两个Item是否有相同的内容(用于判断Item的内容是否发生了改变),* 该方法只有当areItemsTheSame (int, int)返回true时才会被调用。*/override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {return oldModels[oldItemPosition] == newModels[newItemPosition]}/*** 该方法执行时机:areItemsTheSame(int, int)返回true 并且 areContentsTheSame(int, int)返回false* 该方法返回Item中的变化数据,用于只更新Item中变化数据对应的UI*/override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {return super.getChangePayload(oldItemPosition, newItemPosition)}
}

以顶部的Item1 模块举例,当服务端有新数据来时,通过下面方式进行更新:

/*** use[DiffUtil] 增量更新数据* @param newList 新数据*/
fun submitList(newList: MutableList<Any>) {//传入新旧数据进行比对val diffUtil = DataDiffUtil(mModels, newList)//经过比对得到差异结果val diffResult = DiffUtil.calculateDiff(diffUtil)//NOTE:注意这里要重新设置Adapter中的数据setModels(newList)//将数据传给adapter,最终通过adapter.notifyItemXXX更新数据diffResult.dispatchUpdatesTo(this)
}

如果Item1前后数据是一样的,那么DiffUtil.Callback#areContentsTheSame() 中的oldModels[oldItemPosition] == newModels[newItemPosition] 理论上返回的就是true,Item1 模块也不会执行刷新操作了。

实际跑起来能按我们的预期走吗?

问题出现

上述逻辑写的差不多了,还差Model数据类没有写出来,因为项目中是Kotlin & Java混用的,而Model数据类正好是用Java语言编写的:

public class VP2Model implements Serializable {public int id;public String content;
}

看上去一切都是OK的,但是运行之后发现出问题了,即使前后数据完全一样,仍然会进行Item1的刷新,说明DiffUtil.Callback#areContentsTheSame()里的数据对比返回的是false,通过断点发现确实返回了false。

到这里不知道大家有没有发现问题所在?开始以为是数据变了,但是通过Log打点发现前后数据是一样的,那么明明是一样的,为什么对比会是不同呢?仔细一想明白了,问题出在Java语言上,出在VP2Model类中没有重新equals()方法

@Override
public boolean equals(@Nullable Object obj) {return super.equals(obj);
}

Java Model 类默认的equals()方法是比较的对象内存地址,刷新前后生成的显然不是同一个对象,那么前后地址对比返回的肯定是false了,问题就出在了这里!

如果我们使用 Kotlin 语言编写 Model 类就不会有这个问题,因为 Kotlin 编译器自动帮我们重写了equals()/hashCode()方法,如:

data class VP2Model(val id: Int = 0,val content: String = "",
)

注意这里要用data class开头才行,上述代码转换成Java后:

Kotlin data class类转换成Java类自动复写的方法

可以看到 Kotlin 编写的 Model 类自动帮我们实现了其中的equals()/hashCode()方法。

解决方式

已经知道问题出现的原因,那么解决方式就很简单了,比如下面几种解决方式:

方式一

重写Java Model 类中的 equals()方法,对每个字段进行对比,字段都相同返回 true,否则返回 false。

有一种快捷生成方式,在Mac版的 AS 中,可以使用 command + N 的方式生成,如下:

Java中自动实现equals()、hashCode()方法
生成结果:

自动生成

方式二

在使用的地方用 Kotlin语言编写Model 类进行转换,注意:这里一定要用data class 开头的声明,因为 Kotlin 编译器会自动帮我们重写 equals()/hashCode() 方法。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vlc将本地文件推流成ts实时流

推流 打开vlc &#xff0c;打开 媒体----打开网络串流 选择文件选项卡&#xff0c;打开本地文件 点击添加&#xff0c;选择本地的mp3文件 选择串流 点击下拉框&#xff0c;选择udp&#xff0c;点击右边的【添加】按钮 输入媒体流输出地址&#xff0c;点击【下一个】 选择正确的…

大语言模型之十三 LLama2中文推理

在《大语言模型之十二 SentencePiece扩充LLama2中文词汇》一文中已经扩充好了中文词汇表&#xff0c;接下来就是使用整理的中文语料对模型进行预训练了。这里先跳过预训练环节。先试用已经训练好的模型&#xff0c;看看如何推理。 合并模型 这一步骤会合并LoRA权重&#xff0…

PY32F003F18之RTC

一、RTC振荡器 PY32F003F18实时时钟的振荡器是内部RC振荡器&#xff0c;频率为32.768KHz。它也可以使用HSE时钟&#xff0c;不建议使用。HAL库提到LSE振荡器&#xff0c;但PY32F003F18实际上没有这个振荡器。 缺点&#xff1a;CPU掉电后&#xff0c;需要重新配置RTC&#xff…

全国排名前三的直播公司无锋科技入驻天府蜂巢成都直播产业基地

最近&#xff0c;全国排名前三的直播公司——无锋科技&#xff0c;正式宣布入驻位于成都的天府蜂巢直播产业基地&#xff0c;这一消息引起了业内人士的高度关注。成都直播产业基地一直是中国直播产业的重要地标之一&#xff0c;其强大的技术和资源优势为众多直播公司提供了广阔…

每日一题——寻找右区间(排序 + 二分查找)

寻找右区间&#xff08;排序 二分查找&#xff09; 题目链接 理解题目 题目给定一个具有n行2列的二维数组intervals&#xff0c;对于intervals的每一行元素i&#xff0c;就表示一个区间数组&#xff0c;intervals[i][0]即这个区间数组的起始位置start&#xff0c;intervals[i…

十五.镜头知识之景深(Depth of Field)

十五.镜头知识之景深(Depth of Field) 文章目录 十五.镜头知识之景深(Depth of Field)15.1 概述15.2 景深(depth of field)定义15.3 景深原理15.3.1 弥散圆(circle of confusion) 15.4 景深总结 15.1 概述 先看两个例子&#xff0c;拍摄花、昆虫等照片时&#xff0c;背景拍的比…

iphone的safari浏览器实现全屏的pwa模式,并修改顶部状态栏背景颜色

要想修改顶部背景颜色&#xff0c;需要用到这个属性&#xff1a;content就是你要设置的颜色 <!-- 状态栏的背景色 --><meta name"theme-color" content"#f8f8f8" /> 然后再加上下面的设置&#xff1a; <!-- 网站开启对 web app 程序的支持…

使用领域引导图卷积神经网络GCNN增强基于脑电图EEG的神经疾病诊断完整代码

一种基于图卷积神经网络&#xff08;GCNN&#xff09;的新方法&#xff0c;用于改进使用头皮脑电图&#xff08;EEG&#xff09;进行神经系统疾病诊断。尽管脑电图是神经系统疾病诊断中主要使用的检测方法之一&#xff0c;但基于EEG的专家视觉诊断的敏感性仍然只有约50&#xf…

现代卷积网络实战系列4:PyTorch从零构建VGGNet训练MNIST数据集

&#x1f308;&#x1f308;&#x1f308;现代卷积网络实战系列 总目录 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 1、MNIST数据集处理、加载、网络初始化、测试函数 2、训练函数、PyTorch构建LeNet网络 3、PyTorch从零构建AlexNet训练MNIST数据…

【51单片机】10-蜂鸣器

1.蜂鸣器的原理 这里的“源”不是指电源。而是指震荡源。 也就是说&#xff0c;有源蜂鸣器内部带震荡源&#xff0c;所以只要一通电就会叫。 而无源内部不带震荡源&#xff0c;所以如果用直流信号无法令其鸣叫。必须用2K~5K的方波去驱动它。 有源蜂鸣器往往比无源的贵&#xff…

编译和链接

要闯入计算机的世界就逃不过编程这个词&#xff0c;编译和链接是编程过程中的两个重要步骤。在编写源代码后&#xff0c;需要通过编译和链接才能生成可执行文件。 引言——什么是编程 编程是编写程序的中文简称&#xff0c;就是让计算机代为解决某个问题&#xff0c;对某个计算…

C# 自定义控件库之Lable组合控件

1、创建类库 2、在类库中添加用户控件&#xff08;Window窗体&#xff09; 3、控件视图 4、后台代码 namespace UILib {public partial class DeviceInfoV : UserControl{public DeviceInfoV(){InitializeComponent();ParameterInitialize();}#region 初始化private void Par…

pytorch的pixel_shuffle转tflite文件

torch.pixel_shuffle()是pytorch里面上采样比较常用的方法&#xff0c;但是和tensoflow的depth_to_space不是完全一样的&#xff0c;虽然看起来功能很像&#xff0c;但是细微是有差异的 def tf_pixelshuffle(input, upscale_factor):temp []depth upscale_factor *upscale_f…

关于表单快速开发低代码技术平台的内容介绍

运用什么样的表单快速开发软件平台可以实现高效率创收&#xff1f;随着科技的进步和飞速发展&#xff0c;专业的低代码技术平台已经走入了很多企业的办公职场中&#xff0c;它们灵活、轻量级、优质、高效、易维护等优势特点&#xff0c;可以高效助力广大企业提质增效&#xff0…

html、css学习记录【uniapp前奏】

Html 声明&#xff1a;该学习笔记源于菜鸟自学网站&#xff0c;特此记录笔记。很多示例源于此官网&#xff0c;若有侵权请联系删除。 文章目录 Html声明&#xff1a; CSS 全称 Cascading Style Sheets&#xff0c;层叠样式表。是一种用来为结构化文档&#xff08;如 HTML 文档…

ipaguard界面概览

ipaguard界面概览 ipaguard界面分左右2块&#xff1a;左边菜单导航栏&#xff0c;右边的功能区 左侧菜单&#xff1a;按模块分成启动界面&#xff0c;代码模块&#xff0c;文件模块&#xff0c;重签名与测试模块 右侧主功能区会随着功能变化&#xff0c;但是整体分3块&#xf…

vue下载在前端存放的pdf文件

vue下载在前端存放的pdf文件 注意&#xff0c;这里要在public文件夹中新建文件夹存放静态资源&#xff0c;不能在src文件夹中新建文件夹存放静态资源&#xff0c;因为public文件夹中的文件资源不会被npm run build打包编译。大家打包一下&#xff0c;就会发现 模板.pdf文件 是存…

简化任务调度与管理:详解XXL-Job及Docker Compose安装

在现代应用程序开发中&#xff0c;任务调度和管理是至关重要的一部分。XXL-Job是一个强大的分布式任务调度平台&#xff0c;它使得任务的调度和管理变得更加轻松和高效。本文将介绍XXL-Job的基本概念&#xff0c;并详细演示如何使用Docker Compose进行快速安装和配置。 什么是X…

05-前端基础CSS第三天

01-CSS三大特性之层叠性 1.CSS的三大特性 CSS有三个非常重要的三个特性&#xff1a;层叠性、继承性、优先级。 1.1 层叠性 相同选择器给设置相同的样式&#xff0c;此时一个样式就会**覆盖&#xff08;层叠&#xff09;**另一个冲突的样式。层叠性主要解决样式冲突的问题。…

C++——list(2)

作者&#xff1a;几冬雪来 时间&#xff1a;2023年9月28日 内容&#xff1a;C——list内容讲解 目录 前言&#xff1a; list的const迭代器&#xff1a; const的iterator&#xff1a; const迭代器&#xff1a; operator->: 拷贝构造&#xff1a; 迭代器接口补充&…