当前位置: 首页 > news >正文

RecyclerView进阶知识讲解

在 Android 开发中,RecyclerView 是一种高效的列表和网格布局控件,用于显示大规模数据。尽管基本使用方法简单,但深入理解并掌握其高级进阶用法能大幅提升用户体验和应用性能。下面,我将从布局管理、动画和手势、自定义缓存、优化性能等方面系统介绍 RecyclerView 的高级用法。
在这里插入图片描述

目录

  1. 自定义布局管理器
  2. ItemDecoration 装饰
  3. 高级动画控制
  4. 自定义缓存和 RecycledViewPool
  5. 数据差异计算 DiffUtil
  6. 嵌套 RecyclerView 和 ConcatAdapter
  7. 手势交互:拖拽与滑动
  8. 性能优化技巧

1. 自定义布局管理器

LayoutManager 控制 RecyclerView 中每个子项的布局方式。除了 LinearLayoutManagerGridLayoutManager 等系统提供的布局管理器,我们可以自定义 LayoutManager 以实现特殊的布局效果。

示例:创建一个圆形布局管理器
class CircleLayoutManager : RecyclerView.LayoutManager() {private val radius = 300  // 半径private val angleStep = Math.toRadians(360.0 / itemCount)override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams {return RecyclerView.LayoutParams(RecyclerView.LayoutParams.WRAP_CONTENT,RecyclerView.LayoutParams.WRAP_CONTENT)}override fun onLayoutChildren(recycler: RecyclerView.Recycler, state: RecyclerView.State) {detachAndScrapAttachedViews(recycler)val centerX = width / 2val centerY = height / 2for (i in 0 until itemCount) {val view = recycler.getViewForPosition(i)addView(view)measureChildWithMargins(view, 0, 0)val width = getDecoratedMeasuredWidth(view)val height = getDecoratedMeasuredHeight(view)val angle = i * angleStepval x = (centerX + radius * Math.cos(angle) - width / 2).toInt()val y = (centerY + radius * Math.sin(angle) - height / 2).toInt()layoutDecorated(view, x, y, x + width, y + height)}}
}

2. ItemDecoration 装饰

ItemDecoration 用于绘制 RecyclerView 子项的分割线、边框、背景等效果,可以实现比简单的 DividerItemDecoration 更灵活的效果。

示例:实现一个带间距的圆角背景装饰
class RoundedCornerDecoration(private val padding: Int, private val radius: Float) : RecyclerView.ItemDecoration() {private val paint = Paint().apply {color = Color.LTGRAYisAntiAlias = true}override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) {for (i in 0 until parent.childCount) {val child = parent.getChildAt(i)val rect = RectF(child.left.toFloat() + padding,child.top.toFloat() + padding,child.right.toFloat() - padding,child.bottom.toFloat() - padding)canvas.drawRoundRect(rect, radius, radius, paint)}}
}

3. 高级动画控制

RecyclerView 提供了 ItemAnimator 来管理添加、移除和移动等动画效果。我们可以自定义 ItemAnimator,甚至为不同类型的操作设置不同的动画效果。

示例:创建淡入淡出的动画
class FadeInAnimator : DefaultItemAnimator() {override fun animateAdd(holder: RecyclerView.ViewHolder): Boolean {holder.itemView.alpha = 0fholder.itemView.animate().alpha(1f).setDuration(500).start()return true}override fun animateRemove(holder: RecyclerView.ViewHolder): Boolean {holder.itemView.animate().alpha(0f).setDuration(500).start()return true}
}

4. 自定义缓存和 RecycledViewPool

RecyclerView 提供 RecycledViewPool 来缓存多种类型的视图。设置 RecycledViewPool 可以提升多个 RecyclerView 共享视图缓存的效果,适用于嵌套和切换页面的场景。

示例:设置共享 RecycledViewPool
val sharedPool = RecyclerView.RecycledViewPool()
recyclerView1.setRecycledViewPool(sharedPool)
recyclerView2.setRecycledViewPool(sharedPool)

5. 数据差异计算 DiffUtil

DiffUtil 是高效的数据差异计算工具,用于对比旧数据和新数据并生成操作指令。这对于动态数据列表是非常重要的,可以提升性能并减少不必要的刷新。

示例:使用 DiffUtil 优化数据更新
class MyDiffUtilCallback(private val oldList: List,private val newList: List
) : DiffUtil.Callback() {override fun getOldListSize() = oldList.sizeoverride fun getNewListSize() = newList.sizeoverride fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {return oldList[oldItemPosition].id == newList[newItemPosition].id}override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {return oldList[oldItemPosition] == newList[newItemPosition]}
}// 使用 DiffUtil 进行数据更新
val diffResult = DiffUtil.calculateDiff(MyDiffUtilCallback(oldList, newList))
diffResult.dispatchUpdatesTo(adapter)

6. 嵌套 RecyclerView 和 ConcatAdapter

对于多种类型布局需求,可以使用嵌套的 RecyclerViewConcatAdapter 来管理不同的 Adapter,避免复杂的 RecyclerView.Adapter 实现。

示例:使用 ConcatAdapter 管理多个 Adapter
val adapter1 = Adapter1()
val adapter2 = Adapter2()
val concatAdapter = ConcatAdapter(adapter1, adapter2)
recyclerView.adapter = concatAdapter

7. 手势交互:拖拽与滑动

ItemTouchHelper 支持子项拖拽和滑动。通过 ItemTouchHelper.Callback 实现交互逻辑,并附加到 RecyclerView 上。

示例:实现拖拽和滑动删除
val itemTouchHelperCallback = object : ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP or ItemTouchHelper.DOWN, ItemTouchHelper.LEFT
) {override fun onMove(recyclerView: RecyclerView,viewHolder: RecyclerView.ViewHolder,target: RecyclerView.ViewHolder): Boolean {// 处理拖拽逻辑return true}override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {// 处理滑动删除逻辑}
}ItemTouchHelper(itemTouchHelperCallback).attachToRecyclerView(recyclerView)

8. 性能优化技巧

  1. 避免频繁绑定:在 onBindViewHolder 中避免做复杂计算,尽量将静态数据放到 ViewHolder 中。
  2. 预取数据:使用 RecyclerView.setItemViewCacheSize() 或 LinearLayoutManager.setInitialPrefetchItemCount() 来增加缓存。
  3. 调整视图池大小:通过 RecycledViewPool 来共享视图池。
  4. 减少布局嵌套:使用 ConstraintLayout 等优化布局。

通过这些高级用法,可以更灵活地控制 RecyclerView 的行为,从而显著提升应用的用户体验和性能。

参考

Working with RecyclerView in Android & Kotlin

相关文章:

RecyclerView进阶知识讲解

在 Android 开发中,RecyclerView 是一种高效的列表和网格布局控件,用于显示大规模数据。尽管基本使用方法简单,但深入理解并掌握其高级进阶用法能大幅提升用户体验和应用性能。下面,我将从布局管理、动画和手势、自定义缓存、优化…...

C语言 函数

时间:2024.11.10-11.11 一、学习内容 1、什么是函数 函数:程序中独立的功能。将反复书写的代码,又不确定什么时候回用到的代码打包起来。 2、函数的基本格式 函数的定义格式(写在main函数外) void 函数名() { 函数…...

windows中docker安装redis和redisinsight记录

创建一个Redis运行容器,命令如下 docker run -it -d --name redis -p 6379:6379 redis --bind 0.0.0.0 --protected-mode no -d 代表Redis容器后台运行 --name redis 给创建好的容器起名叫redis -p 6379:6379 将容器的6379端口映射到宿主机的6379端口,注…...

itextpdf打印A5的问题

使用A5打印的时候,再生成pdf是没有问题的。下面做了一个测试,在打印机中,使用A5的纸张横向放入,因为是家用打印机,A5与A4是同一个口,因此只能这么放。 使用itextpdf生成pdf,在浏览器中预览pdf是…...

qt QUndoView详解

1、概述 QUndoView 是 Qt 框架中用于显示 QUndoStack(撤销堆栈)内容的视图类。它通常与 QUndoStack 一起使用,为用户提供了一个可视化的界面来查看和操作撤销/重做历史。QUndoView 可以显示堆栈中的每个命令,并允许用户通过界面进…...

python+智谱AI-实现钉钉消息自动回复

python智谱AI-实现钉钉消息自动回复 实现了电脑窗口切换,截图识别未读消息,与语言模型交互后,将答案带入到钉钉窗口中。偷个懒,直接贴代码了,后续不断完善注释,如果遇到读不懂的地方,欢迎交流。…...

Kafka-Eagle的配置——kafka可视化界面

通过百度网盘分享的文件:kafka-eagle-bin-2.0.8.tar.gz 链接:https://pan.baidu.com/s/1H3YONkL97uXbLTPMZHrfdg?pwdsltu 提取码:sltu 一、界面展示 二、软件配置 1、关闭kafka集群 kf.sh stop 2、将该软件上传到/opt/modules下 cd /opt…...

【命令操作】Linux上带宽流量监控nethogs命令详解 _ 统信 _ 麒麟 _ 方德

原文链接:【命令操作】Linux上带宽流量监控nethogs命令详解 | 统信 | 麒麟 | 方德 Hello,大家好啊!今天带来一篇关于Linux上nethogs命令详解的文章。nethogs是一款非常实用的网络流量监控工具,帮助用户实时查看系统中每个进程的网…...

【入门篇】数字统计——多语言版

题目跳转:数字统计 题目解析: 这道题目要求统计在给定范围 [L, R] 内所有整数中数字 2 出现的次数。例如,在范围 [2, 22] 中,数字 2 分别在数 2、12、20、21、22 中出现的次数,最终出现了6次。 题目的输入为两个正…...

探索那些现代C++语法糖

本文来聊聊现代C的一些语法糖。 1.Auto auto x 10; // 推导为 int auto y 3.14; // 推导为 double2.范围-based for 循环 std::vector<int> v {1, 2, 3, 4, 5}; for (auto val : v) {std::cout << val << " "; }3.nullptr int* ptr nullpt…...

【LeetCode】【算法】33. 搜索旋转排序数组

LeetCode 33. 搜索旋转排序数组 题目描述 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k…...

Python小游戏25——黄金矿工

首先&#xff0c;你需要安装Pygame库。 如果你还没有安装&#xff0c;可以使用以下命令进行安装&#xff1a; 【bash】 pip install pygame 【python】代码展示 import pygame import random # 初始化Pygame pygame.init() # 设置屏幕尺寸 screen_width 800 screen_height 60…...

WPF中Prism框架中 IContainerExtension 和 IRegionManager的作用

在Prism框架中&#xff0c;IContainerExtension和IRegionManager扮演着重要的角色&#xff0c;具体作用如下&#xff1a; IContainerExtension IContainerExtension接口是Prism 7中引入的&#xff0c;用于抽象依赖注入容器的操作。它实现了IContainerProvider和IContainerReg…...

C++实现用户分组--学习

第一步实现&#xff1a;ETL的设计分三部分&#xff1a;数据抽取(Data Extraction)、数据的清洗转换(Data Transformation)、数据的加载(Data Loading). 构建一个数据容器类&#xff0c;其中包含转换后的MNIST手写数据。还实现了一个数据处理程序&#xff0c;该数据处理程序将提…...

鸿蒙华为商城APP案例

模拟器运行效果如下&#xff1a; 鸿蒙版APP-华为商城-演示视频...

回首遥望-C++内存对齐的思考

这一章节主要巩固一下学习C/C时内存对齐相关的内容&#xff01; 文章目录 什么是内存对齐&#xff1f;为什么要有内存对齐&#xff1f;如何进行内存对齐&#xff1f;致谢&#xff1a; 什么是内存对齐&#xff1f; 这里不提及一堆啰嗦概念&#xff0c;就结合实际出发&#xff0…...

力扣 LeetCode 704. 二分查找(Day1:数组)

解题思路&#xff1a; 二分查找主要分为[ left , right ]左闭右闭和[ left , right )左闭右开两种 此处采取[ left , right ]左闭右闭写法 注意&#xff1a; 1. right的初始化取值 2. while中取等 3. right mid -1 ; class Solution {public int search(int[] nums, i…...

【Mode Management】AUTOSAR架构下唤醒源检测函数EcuM_CheckWakeup详解

目录 前言 正文 1.AUTOSAR标准描述 1.1 EcuM_CheckWakeup用来干什么 1.2 EcuM_CheckWakeup在哪里被调用 1.3 EcuM_CheckWakeup的使用场景 1.3.1 GPT中断检测唤醒源 1.3.2 EcuM轮询GPT检测唤醒源 1.3.3 ICU中断检测唤醒源 1.3.4 其他 2.AUTOSR工具相关配置 3.唤醒源…...

Zabbix基础信息概述

1.Zabbix概述 Zabbix 是一款能够监控各种网络参数以及服务器健康性和完整性的软件。Zabbix 使用灵活的通知机制&#xff0c;允许用户为几乎任何事件配置基于邮件的告警&#xff0c;这样可以快速反馈服务器的问题。基于已存储的数据&#xff0c;Zabbix 提供了出色的报告和数据可…...

SpringBoot(十二)SpringBoot配置redis

接下来我要实现的webscoket即时聊天中需要使用到redis,我先在项目中配置一下redis。 我这里再windows中做测试,关于redis的安装请移步《Redis(三)Windows系统安装redis》 一:在pom.xml中添加依赖 <!-- springboot redis start --><dependency><grou…...

未授权访问事件频发,我们应当如何应对?

在当下&#xff0c;数据已成为企业和组织的核心资产&#xff0c;是推动业务发展、决策制定以及创新的关键驱动力。然而&#xff0c;未授权访问这一隐匿的安全威胁&#xff0c;正如同高悬的达摩克利斯之剑&#xff0c;时刻威胁着数据的安全&#xff0c;一旦触发&#xff0c;便可…...

软件工程教学评价

王海林老师您好。 您的《软件工程》课程成功地将宏观的理论与具体的实践相结合。上半学期的理论教学中&#xff0c;您通过丰富的实例&#xff0c;将“高内聚低耦合”、SOLID原则等抽象概念解释得十分透彻&#xff0c;让这些理论不再是停留在纸面的名词&#xff0c;而是可以指导…...

项目研究:使用 LangGraph 构建智能客服代理

概述 本教程展示了如何使用 LangGraph 构建一个智能客服代理。LangGraph 是一个强大的工具&#xff0c;可用于构建复杂的语言模型工作流。该代理可以自动分类用户问题、分析情绪&#xff0c;并根据需要生成回应或升级处理。 背景动机 在当今节奏飞快的商业环境中&#xff0c…...

ubuntu系统 | docker+dify+ollama+deepseek搭建本地应用

1、docker 介绍与安装 docker安装:1、Ubuntu系统安装docker_ubuntu docker run-CSDN博客 docker介绍及镜像源配置:2、ubuntu系统docker介绍及镜像源和仓库配置-CSDN博客 docker常用命令:3、ubuntu系统docker常用命令-CSDN博客 docker compose安装:4、docker compose-CS…...

【大厂机试题+算法可视化】最长的指定瑕疵度的元音子串

题目 开头和结尾都是元音字母&#xff08;aeiouAEIOU&#xff09;的字符串为元音字符串&#xff0c;其中混杂的非元音字母数量为其瑕疵度。比如: “a” 、 “aa”是元音字符串&#xff0c;其瑕疵度都为0 “aiur”不是元音字符串&#xff08;结尾不是元音字符&#xff09; “…...

CKA考试知识点分享(2)---ingress

CKA 版本&#xff1a;1.32 第二题是涉及ingress相关。本文不是题目&#xff0c;只是为了学习相关知识点做的实验。 1. 环境准备 需要准备一套K8S集群。 1.1 安装ingress-nginx 下载deploy文件&#xff1a; wget -O controller-v1.12.2.yaml https://raw.githubusercontent…...

MongoDB $type 操作符详解

MongoDB $type 操作符详解 引言 MongoDB 是一款流行的开源文档型数据库,它提供了丰富的查询操作符来满足不同的数据查询需求。在 MongoDB 中,$type 操作符是一个非常有用的查询操作符,它允许用户根据文档中字段的类型来查询文档。本文将详细介绍 MongoDB 的 $type 操作符,…...

【Zephyr 系列 14】使用 MCUboot 实现 BLE OTA 升级机制:构建安全可靠的固件分发系统

🧠关键词:Zephyr、MCUboot、OTA 升级、BLE DFU、双分区、Bootloader、安全固件管理 📌面向读者:希望基于 Zephyr 为 BLE 设备加入安全 OTA 升级功能的开发者 📊预计字数:5200+ 字 🧭 前言:为什么你需要 OTA? 随着设备部署数量增多与产品生命周期延长,远程升级(…...

AWS Elastic Beanstalk + CodePipeline(Python Flask Web的国区CI/CD)

目标 需要使用AWS Elastic Beanstalk 部署一个Python的Flask Web应用&#xff0c;并且使用CodePipeline作为CI/CD工作流。 eb部署图 前提 假设你已经有一个能够正常运行的Python的Flask Web应用项目代码&#xff0c;而且需要对已有Flask工程做一些调整。由于AWS Elastic Bea…...

virtualbox 如何虚拟机ip固定

1、在网络管理里新建 2、配置网络 3、 进入linux系统&#xff0c;查看 查看 网卡是enp0s8, ifconfig 4、进入网卡配置文件 cd /etc/sysconfig/network-scripts如果没有enp0s8 &#xff0c;则使用mv ifcfg-enp0s3 ifcfg-enp0s8命令 配置项如下 TYPEEthernet PROXY_METHODn…...