Android:ViewPager2

2023-11-09

简介

ViewPager2内部使用RecyclerView实现,并提供了增强功能

特性

  • 支持水平、垂直方向布局

android:orientation = “vertical”

  • 支持从右到左

android:layoutDirection = “rtl”

  • 禁止滑动

setUserInputEnabled()

  • 可修改Fragment集合

对可修改的Fragment集合进行分页浏览,底层集合更改时调用notifyDatasetChanged来更新页面

  • 支持DiffUtil

支持局部更新,避免全局更新notifyDatasetChanged全量更新

  • 支持模拟拖拽fakeDragBy

Adapter

由于是内部是RecyclerView,因此可以使用RecyclerView.Adapter<>
若子页为Fragment或Activity,则可使用FragmentStateAdapter

懒加载

当ViewPager2使用FragmentStateAdapter时,可通过setoffscreenPageLimit(int limit)设置离屏缓存数量,当limit<1时,不会进行预加载,默认为-1,VP则是默认为1

可实现加载布局,但不加载数据的懒加载,即在resume调用方法进行加载(handler执行)

当没有设置offscreenPageLimit离屏缓存时,VP2的RecyclerView会缓存前两个Item以及后面预抓取一个Item

设置offscreenPageLimit为1时,会在左右离屏新增一个缓存的Item,即缓存总共5个Item

一屏多页

设置VP2的left和right的padding,并设clipToPadding = false

嵌套滑动冲突

由于ViewPager2内部通过RecyclerView实现,其onInterceptTouchEvent方法返回isUserInputEnabled&&super.onInterceptTouchEvenet

嵌套滑动中的内部控件需要滑动时,设置父控件不拦截事件requestDisallowInterceptTouchEvent(true)
嵌套滑动中的内部控件不需要滑动时,设置父控件不拦截事件requestDisallowInterceptTouchEvent(false)

增量更新DiffUtil

使用DiffUtil进行增量更新,调高性能,使用notifyDatasetChanged进行全量更新
PageDiffUtil内部有方法areItemsTheSame和areContentsTheSame比较两个item和其内容是否相同,前者表示View是否可以复用,后者表示是否需要更新内容 前者返回true时才能调用后者,后者返回fasle才能调用getChangePayLoad,用于更新对应Item

//使用DiffUtil更新数据
val callback = PageDiffUtil(mItems, newItems)
val difResult = DiffUtil.calculateDiff(callback)
mItems.clear()
mItems.addAll(newItems)
difResult.dispatchUpdatesTo(adapter)

转场动画Transformer

val multiTransformer = CompositePageTransformer()
multiTransformer.addTransformer(ScaleInTransformer())
multiTransformer.addTransformer(MarginPageTransformer(10))
ViewPager2.setPageTransformer(multiTransformer)

RecyclerView缓存机制

RecyclerView通过内部类Recycler管理缓存,RecyclerView本身时一个ViewGroup,滑动时需要增删子View,Recycler缓存的是ViewHolder,便于复用子View和绑定的数据

四级缓存

  • mAttachedScrap: ArrayList< ViewHolder >类型

缓存屏幕中可见范围的ViewHolder
不重新创建视图和绑定数据

  • mCachedViews: ArrayList< ViewHolder >类型

缓存滑动时即将与RecyclerView分离的ViewHolder,按position或id缓存,默认缓存数量为2
不重新创建视图和绑定数据

  • mViewCacheExtension: ViewCacheExtension类型

开发者自行实现的缓存
不重新创建视图和绑定数据

  • mRecyclerPool: RecycledViewPool类型

ViewHolder缓存池,本质为SparseArray,key为ViewType(int),value存放的是ArrayList< ViewHolder>,ArrayList默认存放5个ViewHolder
不重新创建视图,但重新绑定数据

mAttachedScrap、mCachedViews官方视为同一级

RecyclerView滑动时触发onTouchEvent#onMove,此时会进行回收和复用ViewHolder,这部分工作由LayoutManager负责

当RecyclerView重新布局时会依次执行下面几个方法
onLayoutChildren():对RecyclerView进行布局的入口方法
fill():负责对剩余空间进行不断填充,调用layoutChunk()
layoutChunk():填充View,最终通过Recycler中找到合适的View

onLayoutChildren() —> fill() —> layoutChunk() —> next() —> getViewForPosition()
getViewForPosition() 是从RecyclerView的回收机制实现类Recycler中获取合适的View

getViewForPosition() 就是依次通过四级缓存查找对应的ViewHolder,若都找不到则重新创建

ViewCacheExtension

第三级缓存,开发者自定义缓存
mAttachedScrap用来处理可见屏幕的缓存,而mCachedViews里存储的数据根据position来缓存,里面的数据随时可能会被替换
mRecyclerPool则按ViewType为key存储,不能按position存储,且还得重新绑定数据,而业务汇总优势需要在特定位置一直展示某个view,其内容不变,为避免重新创建View和重新绑定数据

与ListView缓存机制对比

mAttachedScrap和mCachedViews、mRecyclerViewPool能够快速重用itemView
而RecyclerView的优势在于对mCachedViews的使用,无需重新创建和绑定数据
mRecyclerPool可供多个RecyclerView共同使用,对缓存机制进行补强和完善,对于频繁更新和局部刷新等,RecyclerView更强大和完善

offscreenPageLimit离屏缓存

setOffscreenPageLimit设置的是VP2的离屏显示个数,默认是-1,
因为RecyclerView中的布局是通过LayoutManager,所以真正进行离屏计算是在VP2.LinearLayoutManagerImpl#calculateExtraLayoutSpace()中
该方法计算的是LinearLayoutManager布局的额外空间,LinearLayoutManagerImpl继承自LinearLayoutManager。

getPageSize()表示ViewPager2的宽度,左右离屏大小都为getPageSize() * pageLimit。extraLayoutSpace[0]表示左边,extraLayoutSpace[1]表示右边。
比如设置offscreenPageLimit为1,可以认为是把屏幕扩大到3倍。
左右两边各有一个离屏PageSize的宽度(左右不可见)
在这里插入图片描述

FragmentStateAdapter缓存

FragmentStateAdapter继承自RecyclerView.Adapter,所以可以直接通过setAdapter设置给VP2。我们知道FragmentStateAdapter作为Adapter时,每个Item都是Fragment

每个Fragment内部根布局为FrameLayout,并设置唯一ID
FragmentStateAdapter内部有两个数组,分别存储position分别对Fragment和ID的映射表
当VP2滑动时,当前页前两个item会被缓存到mCachedViews中,超过2个时,将其转移到RecyclePool中

当 当前页为最后一页时,会缓存前三个页面

而当第一次加载时,没有onTouch操作,不会进行预抓取

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android:ViewPager2 的相关文章

随机推荐

  • ESP32S2+VOIP移植- 481 call/transaction does not exist

    ESP32 SIP调试时一定注意 481 call transaction does not exist 问题 除了要注意Request URI Call ID Tag等一致性问题还有一个关键就是 CANCEL ACK 的CSeq 后的数字
  • Lottie 动效调研与实践

    Lottie 概述 https airbnb design lottie Lottie 官网 Lottie 是一个支持多端展示的动效库 相对于 OpenGL 动画 GIF Lottie 有着他独有的一些优点和优势 例如对比原生动画 api
  • wrk 性能测试带参数的接口

    wrk在使用带参数的接口进行压测时 参数会被过滤掉 比如 http 127 0 0 1 8080 benchmark name 1 userId 1 sex 1 这个接口 执行压测命令如下 wrk t5 c5 d30s http 127 0
  • 跨域请求中预检请求options之坑

    一 前言 因为跨域请求 浏览器可能 后面讲 会发送一次options请求 如果处理不好 跨域还是会gg的 之前很少涉及跨域 涉及也是简单请求 下面阮老师文章中区别热简单请求和复杂请求 所以基本不会很少关注options 后面就遇到坑了 下面
  • 【刷题版】掌握算法的一揽子计划——动态规划总结

    动态规划是一种通过将原问题分解为相对简单的子问题来求解 然后将子问题的解存储起来避免之后重复计算 并最终将子问题组合成原问题的解决方法 动态规划并不算是一种具体的算法 更应该被认为是一种解决问题的思想 动态规划通常适用于具有重叠子问题和最优
  • python开发库安装(pycharm)

    开发库安装 过程比较简单 随意说一下 这里我们使用的是pycharm这个开发工具 直接在pycharm中下载就可以 比较简单 看下面图片 第一步 第二部 第三步 搜索你想要安装的库 点击下面的安装就可以 提示安装成功就可以使用了 这里给大家
  • axios请求缓存

    源代码 import axios from axios 数据存储 export const cache data set key data bol false if bol localStorage setItem key JSON str
  • 百度搜索jquery自动完成补全插件autocomplete

    百度搜索框效果 这东西有个 专用的插件 jquery自动补全插件autocomplete js 专治这个 我也是才知道 真是孤陋寡闻 jQuery Autocomplete实现自动完成功能 搜索提示功能 罗曼飞羽 博客园 这里有讲 jque
  • 类型转换与运算符

    一 自动转换 隐士转换 当小范围数据向大范围数据转换时 会发生自动转换 二 强制转换 占内存大的数据向占内存小的转换时 会发生强制转换 如 int a 1 三 运算符 1 关系运算符 2 逻辑运算符 3 算术运算符 4 赋值运算符 5 字符
  • 基于深度学习lstm_基于LSTM的深度恶意软件分析

    基于深度学习lstm Malware development has seen diversity in terms of architecture and features This advancement in the competen
  • mac 环境安装Libpng

    采用brew的安装方式如果没有brew需要先安装brew 如果是第一次用brew安装软件 在安装Libpng 之前要先运行下 brew install xz 否则会报错 如果运行brew install xz 报错 是因为 usr loca
  • ubuntu install phabricator with nginx

    Installing Required Components If you are installing on Ubuntu or an RedHat derivative there are install scripts availab
  • android init.rc文件语法详解

    初始化语言包含了四种类型的声明 Actions 行动 Commands 命令 Services 服务 和Options 选项 基本语法规定 1 所有类型的语句都是基于行的 一个语句包含若干个tokens token之间通过空格字符分隔 如果
  • 干货!Jenkins下配置findbugs、pmd及checkstyle实现代码自动检测

    配置前提 对于maven项目来说 需要在pom xml文件的
  • 小程序项目实战(一)

    项目名称 音乐小程序项目 讲师 coderwhy 学习链接 小程序音乐项目开发实战 大神coderwhy新课 学习视频教程 腾讯课堂课程简介https ke qq com course 4162214 此博客用来总结自己学习小程序开发的知识
  • PCL 查看点云数据中包含的属性信息

    目录 一 概述 1 主要函数 2 算法源码 二 代码实现 三 结果展示 一 概述 PCL中自带的调用函数可直接查看点云数据中包含的有效属性信息 如RGB XYZ 法向量等 以下代码展示如何进行获取 1 主要函数 pcl getFieldsL
  • Github标星超级牛,免费又好用的Redis客户端工具!

    RedisDesktopManager 以前一直使用的是RedisDesktopManager这款Redis客户端工具 由于很久 这个工具大家相对不陌生了 也很多人都使用过了 RedisLettuceClient 他的界面这样 熟悉不 而且
  • 嵌入式CGI开发之旅——CGI环境变量

    嵌入式CGI开发之旅 CGI环境变量 WEB服务器和CGI FastCGI程序之间交流信息的主要途径是环境变量 以及标准输入输出流 这里说的环境变量是指操作系统中的环境变量 windows系统下 PATH是很常见的一个环境变量 CGI规范对
  • [高光谱]PyTorch使用CNN对高光谱图像进行分类

    项目原地址 Hyperspectral Classificationhttps github com eecn Hyperspectral ClassificationDataLoader讲解 高光谱 使用PyTorch的dataloade
  • Android:ViewPager2

    简介 ViewPager2内部使用RecyclerView实现 并提供了增强功能 特性 支持水平 垂直方向布局 android orientation vertical 支持从右到左 android layoutDirection rtl