解决安卓中RecyclerView当一项被点击之后,后面每间隔相同的一段都会有其它项被点击

news/2024/10/17 16:22:49/

文章目录

  • 问题描述
  • 缘由
  • 解决办法 1:提高缓存容量
  • 解决办法 2:每次在初始化视图数据之前重置视图数据
  • 解决办法 3:优化设计,不在视图中储存数据

问题描述

  安卓开发会有很多很多莫名其妙的坑。笔者在使用 RecyclerView 的过程中,发现一个很奇怪的事情。当 RecyclerView 有一项被点击之后,后面每间隔相同的一段都会有其它项被点击。经过笔者不断查看日志,这才发现问题所在。

笔者报错时的运行环境:

  • Android Studio Flamingo | 2022.2.1

  • Android SDK 33

  • Gradle 8.0.1

  • JDK 17

  • RecyclerView 1.2.1

缘由

  原来是因为 RecyclerView 为了提高效率,于是使用缓存。然后后来在若干项之后,并没有创建新的视图 View,而直接循环复用了原来的视图,因此导致视图脏读,从而发生以上的问题。

  具体来说,RecyclerView 要求适配器 RecyclerView.Adapter<?> 至少提供两个方法:onCreateViewHolder、onBindViewHolder。第一个方法用于创建视图,第二个方法用于初始化视图数据。问题在于,RecyclerView 在若干项之后,就不再调用 onCreateViewHolder,而是选择直接循环复用缓存中的视图数据,然后调用 onBindViewHolder 来进行初始化。

解决办法 1:提高缓存容量

  很遗憾,安卓没有提供关闭缓存的 API。安卓很多组件都有一些错误设计,这种现象太普遍了,笔者早已习惯了。现实就是要在不良的环境下解决各种疑难杂症。

  RecyclerView 支持设置缓存容量。因此,只需要将缓存容量设置为与数据项的数量一样即可。

recyclerView.setItemViewCacheSize(/* RecyclerView 列表数据项的数量 */);

  不过,这种方法非常笨拙,有一些隐患。首先是性能的问题,这毋庸置疑。RecyclerView 复用视图本来就是为了提高性能。另一个问题是,如果向 RecyclerView 增加了一些项,此时需要同步变更缓存容量。如果删除了一些项,则缓存可能还会发生混乱。这是一个安全问题。

解决办法 2:每次在初始化视图数据之前重置视图数据

  很遗憾,安卓同样没有提供一键重置视图 View 数据的 API,所以需要自己手动自定义代码重置。具体重置哪些数据呢?上次变更了更些数据,这次初始化视图数据之前(调用 onBindViewHolder 方法刚开始时)就要重置哪些数据。这种说法看起来很奇怪,为什么后面已经要初始化了,前面还要重置呢?这很好理解。因为一般只有不同视图数据不同的部分才需要初始化的,相同的数据是直接使用布局文件的默认值而不进行初始化。

  比如,如果上次添加了鼠标点击按钮变色事件,那么这次就需要先把按钮颜色恢复至默认值。因为后面初始化数据的时候并不会再设定按钮的背景颜色。总之,上次变更了更些数据,这次初始化视图数据之前就要重置哪些数据。

  不过,这种方法也比较笨拙,首先它耦合度很高,需要记住上次视图变化的每个细节。另外,这种方法也有安全问题。因为每次都重置视图数据,所以当滑动到下面的项时,前面视图的数据就被清空了。比方说,如果上次使得按钮变色,当滑动到下面的项,然后再滑回来时,前面那个按钮的颜色也会恢复原状。

解决办法 3:优化设计,不在视图中储存数据

  已经知道,前面的 解决办法 1解决办法 2 都各自有一些问题。这些问题的症结在于,RecyclerView 在设计的时候认为开发者不会在视图 View 中储存任何数据。因此,读者在开发的过程中需要区分,共性数据与个性化数据,视图数据空间与数据库数据空间。如果把个性化数据储存在视图数据空间,就会导致 bug。所以,最好的办法是不要在视图 View 中储存数据。

  比如上面举例的点击按钮变色问题,不应该让视图 View 来储存这种颜色变化,而应该使用其它单独的数据结构来储存。这样设计起来就没有安全隐患。


http://www.ppmy.cn/news/55601.html

相关文章

PHP面试宝典之Redis下篇

redis主从同步&#xff1f; 全量同步&#xff1a; 什么时候进行全量同步&#xff1f; 1&#xff1a;从节点第一次连接主节点时 2&#xff1a;从节点断开时间太久&#xff0c;日志中的offset被覆盖时 全量同步的过程&#xff1f; 1&#xff1a;从节点请求增量同步 2&…

Word论文自动化排版

论文的总体结构包含了标题、正文、子标题、图形、公式、算法、表格、参考文献等子结构。在利用Word进行论文排版时常常遇到这些困难&#xff1a;&#xff08;1&#xff09;论文的各子结构的格式非常难以做到统一&#xff0c;而且一旦某一子结构的格式需要修改&#xff0c;则需要…

Linux从入门到精通一般要学习多久?

如果一般操作的话&#xff0c;很简单学会&#xff0c;用不了多长时间&#xff0c;和一般的window操作系统一样具有图形界面&#xff0c;操作起来十分方便&#xff0c;Linux中也有WPS办公系统&#xff0c;、Linux上的应用程序没有windows上那么丰富&#xff0c;但也能满意一般用…

一些关于单链表的操作

思维导图&#xff1a; 一&#xff0c; 链表 1.1节点的结构 链表是啥样的啊&#xff1f;顾名思义链表就是一种用链子链接起来的表。那这种表是怎么样的啊&#xff1f; 这样的呗&#xff1a; 现在&#xff0c;我们知道了链表的形状了。那我们该如何用编程语言来形成这一种形状…

倾斜摄影超大场景的三维模型轻量化纹理压缩的关键技术

倾斜摄影超大场景的三维模型轻量化纹理压缩的关键技术 倾斜摄影超大场景的三维模型轻量化处理中纹理压缩是轻量化处理的重要手段之一&#xff0c;可以在保证模型真实感的前提下&#xff0c;减小数据体积、降低传输带宽和提高渲染性能。以下是几个关键的纹理压缩技术&#xff1a…

边缘计算在哪些场景的应用?实现了哪些功能

边缘计算是一种分布式计算模型&#xff0c;将数据处理和存储功能从云中心移动到接近数据源的边缘设备上&#xff0c;从而在处理延迟、网络带宽、隐私保护和数据安全等方面带来了许多优势。 智慧油站应用&#xff1a;在加油区部署的吸烟检测、打电话检测、烟火检测、区域入侵检测…

配置Bridge模式KVM虚拟机

配置Bridge模式KVM虚拟机 1. 配置基本环境 1 安装软件包。 安装brctl和tunctl命令行工具&#xff0c;要采用Bridge模式的网络配置&#xff0c;首先需要安装两个RPM包&#xff0c;即bridge-utils和tunctl&#xff0c;它们提供所需的brctl和tunctl命令行工具。可以用yum工具安…

【go】channel结构体源码和读写和关闭过程

简而言之&#xff0c;channel维护了一个带指针的接受和发送的队列,其中包含mutex锁保证并发安全&#xff0c;数据类型&#xff0c;元素个数&#xff0c;元素大小&#xff0c;channel状态然后读写操作&#xff0c;先看队列是否可以取出&#xff0c;然后看缓冲区&#xff0c;最后…