【动画图解】这个值取对了,ViewPager2才能纵享丝滑
前言
在前两篇文章中,我们通过一张张清晰明了的「示意图」,详细地复盘了RecyclerView「缓存复用机制」与「预拉取机制」的工作流程,这种「图解」创作形式也得到了来自不同平台读者们的一致认可。
而从本文开始,我们将正式进入ViewPager2的篇章,并将辅以更加生动易懂的「动态示意图」来进行讲解。
ViewPager2可讲的内容有很多,今天我们主要介绍是ViewPager2的「离屏加载机制」,你可能是第一次听说这个术语,但在实际开发中,你肯定使用过它,因为它对应的配置入口,就是ViewPager2的OffscreenPageLimit属性。
OffscreenPageLimit是什么?
OffscreenPageLimit,直译过来是离屏页面限制值的意思,该值代表的是在滑动视图中应保留在当前可见页面之外的任一方向上的页面数。
比如,当我们采用水平分页时,该值代表的便是在左右两侧应保留的页面数。
而当我们采用垂直分页时,该值代表的则是在上下两侧应保留的页面数。
保留页面的方式是通过扩展额外的布局空间实现的,以LinearLayoutManager为例,其最关键的步骤在于对calculateExtraLayoutSpace
方法的重写:
/*** 计算额外的布局空间*/@Overrideprotected void calculateExtraLayoutSpace(@NonNull RecyclerView.State state,@NonNull int[] extraLayoutSpace) {int pageLimit = getOffscreenPageLimit();if (pageLimit == OFFSCREEN_PAGE_LIMIT_DEFAULT) {// 仅在需要时才对屏幕外页面进行自定义预取super.calculateExtraLayoutSpace(state, extraLayoutSpace);return;}// 计算多pageLimit*2个页面大小的空间final int offscreenSpace = getPageSize() * pageLimit;extraLayoutSpace[0] = offscreenSpace;extraLayoutSpace[1] = offscreenSpace;}/*** 获取单个页面大小*/int getPageSize() {final RecyclerView rv = mRecyclerView;// 水平分页时,取去除了左右内边距后的RecyclerView宽度// 垂直分页时,取去除了上下内边距后的RecyclerView高度return getOrientation() == ORIENTATION_HORIZONTAL? rv.getWidth() - rv.getPaddingLeft() - rv.getPaddingRight(): rv.getHeight() - rv.getPaddingTop() - rv.getPaddingBottom();}
该方法会计算LinearLayoutManager应布置的额外空间量(以像素为单位)。已知默认布置的空间量为单个页面大小,则额外布置的空间量应为OffscreenPageLimit*2个单页面大小,计算出来的结果会存储在int数组类型的extraLayoutSpace
结构中,其中:
- extraLayoutSpace[0]应用于顶部或左侧的额外空间;
- extraLayoutSpace[1]应用于底部或右侧的额外空间。
虽然这部分额外创建的页面在当前屏幕上并不可见,但实际已经被添加至我们的视图层次结构中了。这么做可以减少切换分页时花费在视图创建与布局上的时间,从而提升ViewPager2滑动时的整体流畅度。
结合前面两篇文章我们可以看到,从缓存复用机制到预拉取机制再到现在的离屏加载机制,RecyclerView与ViewPager2在提升滑动流畅度方面真的是做了非常多的努力。
区别在于:
- 缓存复用机制是通过缓存已创建的页面,以提供给新进入屏幕的页面重用来实现的。
- 预拉取机制是通过利用UI线程空闲的时机,提前创建并缓存下一个待进入屏幕的页面来实现的。
- 离屏加载机制则是通过扩展额外的布局空间,以提前创建并保留屏幕两侧的页面来实现的。
从调用方法流程上讲,离屏加载机制除了常规的onCreateViewHolder、onBindViewHolder方法之外,还会执行一个多onViewAttachedToWindow
方法,以将页面提前添加至我们的视图层次结构中。
虽然我们一直强调的是“ViewPager2的离屏加载机制”,但其实,离屏加载机制并不是ViewPager2才引入的新特性,作为ViewPager的改进版本,ViewPager2也只是把早已存在于ViewPager中的这个特性照搬过来而已,二者的主要区别有以下几点:
- 对于OffscreenPageLimit默认值的设置
- 对于OffscreenPageLimit赋值条件的限制
OffscreenPageLimit的默认值设置与赋值条件限制
ViewPager一直为人所诟病的一个点就是,其设置的OffscreenPageLimit默认值为1,且不允许外部传入低于1的修改值,即会强制开启离屏加载机制。
// 默认的离屏加载限制值为1private static final int DEFAULT_OFFSCREEN_PAGES = 1;public void setOffscreenPageLimit(int limit) {// 小于默认值的数会被强制设为默认值if (limit < DEFAULT_OFFSCREEN_PAGES) {Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to "+ DEFAULT_OFFSCREEN_PAGES);limit = DEFAULT_OFFSCREEN_PAGES;}if (limit != mOffscreenPageLimit) {mOffscreenPageLimit = limit;populate();}}
// 谁赞成,谁反对
这也就意味着,在使用ViewPager构建的滑动视图中,不管开发者需不需要,都至少会有1~2个页面会被离屏加载,而这会导致一系列依赖于Fragment生命周期的逻辑被异常执行,进而产生非预期的结果,需要开发者手动实现延迟加载机制。
相比较之下,ViewPager2设置的OffscreenPageLimit默认值则为-1,也即默认不开启离屏加载机制,且对于外部传入的修改值也只要求必须是大于0的正数或默认值。
// 默认的离屏加载限制值为-1public static final int OFFSCREEN_PAGE_LIMIT_DEFAULT = -1;public void setOffscreenPageLimit(@OffscreenPageLimit int limit) {// 低于1且非默认值的传参会报异常if (limit < 1 && limit != OFFSCREEN_PAGE_LIMIT_DEFAULT) {throw new IllegalArgumentException("Offscreen page limit must be OFFSCREEN_PAGE_LIMIT_DEFAULT or a number > 0");}mOffscreenPageLimit = limit;// 触发重新布局操作,以便通过getExtraLayoutSize()方法进行离屏加载mRecyclerView.requestLayout();}
另外,我们在本系列的第一篇就讲了,ViewPager2是在RecyclerView的基础上构建而成的。因此,即使是默认不开启离屏加载机制,预拉取机制也会正常工作。
而我们前面又讲了,预拉取机制会提前创建并缓存下一个待进入屏幕的页面,但不会添加至我们的视图层次结构中,因此不会像ViewPager一样,导致一系列依赖于Fragment生命周期的逻辑被异常执行,相当于自动帮我们实现延迟加载机制了。
从以上2个默认数值我们可以看到,无论是ViewPager还是ViewPager2,其对于OffscreenPageLimit默认值的设置都是比较克制的。实际上,在setOffscreenPageLimit方法的注释中,Android也是建议我们将此限制值保持在较低水平,尤其是当我们的页面具有复杂的布局时。
但实际情况是,大部分的开发者为图方便,往往会将此值设为页面总数-1,也即默认会离屏加载所有的页面。
这种做法无疑是很不规范的,为什么说不规范呢?这就引申出我们下一个问题了,即OffscreenPageLimit的不同赋值,会对ViewPager2产生什么样的影响呢?
不同的OffscreenPageLimit值产生的影响
行为表现
OffscreenPageLimit值为-1
当OffscreenPageLimit值为-1时,也即保持默认不开启离屏加载机制,这种情况下只有RecyclerView的缓存复用机制和预拉取机制会工作。
- 当滑动视图初始化完成时,只有position=0的页面项会被添加至当前视图层次结构中。
- 随着我们往左滑动屏幕,预拉取机制会开始工作,提前创建position=2的页面项并放入mCachedView中。
- 同时,position=0的页面项也将随着向左滑动的手势被移出屏幕,并放入mCachedView中。
- 再次向左滑动屏幕,滑动视图会取出预拉取的position=2的页面项进行使用,同时开启对position=3的页面项的预拉取。
- 此时,由于还未超过mCachedView大小的限制,下一个被移出屏幕的position=1的页面项也将放入mCachedView中。
- 第三次向左滑动屏幕,同样,会取出预拉取的position=3的页面项进行使用,同时开启对position=4的页面项的预拉取。
- 但是,由于超过了mCachedView大小的限制,在下一个被移出屏幕的position=2的页面项尝试进入时,会先按照先进先出的顺序,先从mCachedView中移出position=0的页面项,放入RecyclerPool中对应itemType的ArrayList容器中,然后position=2的页面项才顺利进入mCachedView。
- 之后的滑动同样遵循这个规律,不再赘述。
OffscreenPageLimit值为1
当OffscreenPageLimit值为1时,也即会在左右两侧各离屏加载1个页面。
- 当滑动视图初始化完成时,由于左侧无更多的页面项,因此只有position=0及position=1的页面项会被添加至当前视图层次结构中。
- 随着我们往左滑动屏幕,position=2的页面项会被添加至当前视图层次结构中,而position=0的页面项会继续保留在当前视图层次结构中,同时预拉取机制会开始工作,提前创建position=3的页面项并放入mCachedView中。
- 再次向左滑动屏幕,滑动视图会取出预拉取的position=3的页面项添加至当前视图层次结构中,而position=1的页面项会继续保留在当前视图层次结构中,并开启对position=4的页面项的预拉取。
- 同时,position=0的页面项也将随着向左滑动的手势被移出屏幕,并放入mCachedView中。
- 第三次向左滑动屏幕,同样,会取出预拉取的position=4的页面项添加至当前视图层次结构中,并保留position=2的页面项在当前视图层次结构中,同时开启对position=5的页面项的预拉取。
- 此时,由于还未超过mCachedView大小的限制,下一个被移出屏幕的position=1的页面项也将放入mCachedView中。
- 第四次向左滑动屏幕,同样,会取出预拉取的position=5的页面项添加至当前视图层次结构中,并保留position=3的页面项在当前视图层次结构中,同时开启对position=6的页面项的预拉取。
- 但是,由于超过了mCachedView大小的限制,在下一个被移出屏幕的position=2的页面项尝试进入时,会先按照先进先出的顺序,先从mCachedView中移出position=0的页面项,放入RecyclerPool中对应itemType的ArrayList容器中。
OffscreenPageLimit值为3
当OffscreenPageLimit值为3时,也即会在左右两侧各离屏加载3个页面。
- 当滑动视图初始化完成时,由于左侧无更多的页面项,因此只有position=0至position=3的页面项会被添加至当前视图层次结构中。
- 随着我们往左滑动屏幕,position=4的页面项会被添加至当前视图层次结构中,而position=0的页面项会继续保留在当前视图层次结构中,同时预拉取机制会开始工作,提前创建position=5的页面项并放入mCachedView中。
- 再次向左滑动屏幕,滑动视图会取出预拉取的position=5的页面项添加至当前视图层次结构中,而position=1的页面项会继续保留在当前视图层次结构中,并开启对position=6的页面项的预拉取。
- 第三次向左滑动屏幕,滑动视图会取出预拉取的position=6的页面项添加至当前视图层次结构中,而position=2的页面项会继续保留在当前视图层次结构中。也即这个时候,所有的页面项已经都被添加至当前视图层次结构中了。
- 第四次向左滑动屏幕,由于超出了OffscreenPageLimit值,position=0的页面项将随着向左滑动的手势被移出屏幕,并放入mCachedView中。
- 第五次向左滑动屏幕,此时,由于还未超过mCachedView大小的限制,下一个被移出屏幕的position=1的页面项也将放入mCachedView中。
- 第六次向左滑动屏幕,但是,由于超过了mCachedView大小的限制,在下一个被移出屏幕的position=2的页面项尝试进入时,会先按照先进先出的顺序,先从mCachedView中移出position=0的页面项,放入RecyclerPool中对应itemType的ArrayList容器中。
OffscreenPageLimit值为页面总数-1
当OffscreenPageLimit值为页面总数-1时,也即在滑动视图初始化完成时就已经离屏加载所有的页面了,这种情况下RecyclerView的缓存复用机制和预拉取机制完全没有工作的机会。
虽然设置更高的OffscreenPageLimit值,可以更好地提升ViewPager2滑动时的流畅度,但由于需要在初始化阶段同时创建多个页面项,意味着将花费更久的创建时间,页面项内容也将更慢显示,同时,由于两侧有更多的页面项被保留而不走缓存复用流程,意味着应用会占用更多的内存,且这些问题将随着页面复杂度提升更加突出。
为了更直观地展示不同的OffscreenPageLimit值对应用的性能影响,我们将从白屏时间、流畅度、占用内存三个维度来进行横向对比:
性能影响
白屏时间
可以看到,随着OffscreenPageLimit值的增加,在滑动视图的初始化阶段,会有更多的页面项需要被创建并被添加至当前的视图层次结构中,白屏时间也随之延长。
流畅度
参考上一篇的做法,我们同样在FragmentStateAdapter中对Fragment的视图准备工作做了延迟,以在GPU渲染模式中展示更加清晰的柱状图:
OffscreenPageLimit值为1时,虽然可以离屏加载下一个页面,但由于每次滑动还要执行预拉取的工作,因此对于流畅度的提升不是很明显。
OffscreenPageLimit值为3时,即每次都会保留当前屏幕两侧的各3个页面项,在滑动到中间位置时,对于流畅度的提升是最大的,此时无论是往前滑还是往后滑,都无需再执行页面项的创建工作,即使滑到边界也可以利用缓存复用机制来重用视图。
OffscreenPageLimit值为6时,也即在滑动视图初始化完成时就已经离屏加载所有的页面了,每次的滑动就相当于只是在当前的视图层次结构中进行位移,因此全程的流畅度都有极大的提升。
内存占用
可以看到,随着OffscreenPageLimit值的增加,在滑动视图的初始化阶段,会有更多的Fragment对象驻留在内存中。
同时,由于OffscreenPageLimit值会保留当前屏幕两侧的页面项,因此,滑动到中间位置时,OffscreenPageLimit值为1的情况最多会保留3个Fragment对象,而OffscreenPageLimit值为3的情况最多会保留7个Fragment对象。
但在其他位置时,它会将超出OffscreenPageLimit值限制的页面将从视图层次结构中移除,并交由RecyclerView的缓存复用机制处理,同往常一样回收ViewHolders对象以供重用。
OffscreenPageLimit值取多大比较合适?
现在我们知道了,当OffscreenPageLimit值设得过大,比如页面总数-1时,会给应用带来比较大的内存压力,特别是在部分低端机型上。
而OffscreenPageLimit值设得过小,比如1时,又无法发挥出离屏加载机制提高页面滑动流畅度的优势。
一般来讲,同时保持3-4个页面项处于活动状态是一个比较合适的值,一方面,可以提高用户来回翻页时的流畅度,另一方面又不会给应用带来太大的内存压力。当然,还需要我们自己维护好Fragment重建以及视图回收/复用时的处理逻辑。
最好的情况下,还是希望能够根据应用当前的内存使用情况,对该值进行动态调整,在行为表现与性能影响上取一个平衡点。
但如果多个页面项之间存在互斥关系,同时处于活动状态可能影响业务的判断时,保持OffscreenPageLimit为默认值,也即默认关闭离屏加载机制,只让预拉取机制与缓存复用机制工作,也许是个更好的选择。
后记
讲到这里,相信你对ViewPager2的离屏加载机制已经有了一定的认识,但不知道你发现没有,我们全文讲的都是ViewPager2顺序依次翻页的情况,但在实际运用中,我们常常会搭配TabLayout,提供点击标签页跳转到指定页面项的功能。
而当增加了这一种新的交互方式后,问题的维度再一次上升了,我们会发现离屏加载机制的行为逻辑又有所不同了,而这,就是下一篇的内容了。
相关文章:
【动画图解】这个值取对了,ViewPager2才能纵享丝滑
前言 在前两篇文章中,我们通过一张张清晰明了的「示意图」,详细地复盘了RecyclerView「缓存复用机制」与「预拉取机制」的工作流程,这种「图解」创作形式也得到了来自不同平台读者们的一致认可。 而从本文开始,我们将正式进入Vi…...
CSDN每日一练:小豚鼠搬家
题目名称:小豚鼠搬家 时间限制:1000ms内存限制:256M 题目描述 小豚鼠排排坐。 小艺酱买了一排排格子的小房子n*m,她想让k只小豚鼠每只小豚鼠都有自己的房子。 但是为了不浪费空间,她想要小房子的最外圈尽量每行每列都有…...
Dockerfile命令及实践构建一个网站
dockerfile用于构建docker镜像的,部署一个用于运行你所需的容器环境。相当一个脚本,通过dockerfile自己的指令,来构建软件依赖、文件依赖、存储、定制docker镜像的方式有两种:手动修改容器内容,导出新的镜像基于Docker…...
[VMware]Ubuntu18.04 网络图标消失
Ubuntu 18.04 网络图标消失运行环境问题解决NO.1 执行 sudo systemctl stop network-managerNO.2 执行 sudo rm /var/lib/NetworkManager/NetworkManager.stateNO.3 执行 sudo systemctl start network-managerNO.4 vi /etc/NetworkManager/NetworkManager.confNO.5 执行 sudo …...
国产C2000,P2P替代TMS320F280049C,独立双核32位CPU,主频高达400MHz
一、特性参数 1、独立双核,32位CPU,单核主频400MHz 2、IEEE 754 单精度浮点单元 (FPU) 3、三角函数单元 (TMU) 4、1MB 的 FLASH (ECC保护) 5、1MB 的 SRAM (ECC保护&…...
二十五、Gtk4-多线程分析
1 回顾 1.1 Gnome相关 首先回顾一下GLib,GObject,GIO,Gtk的不同,因为下面会涉及到这些概念里面的函数。 所有这些都是由Gnome项目开发的库,一般都用于Gnome环境相关的应用程序。 Gtk:GUI界面库。GLib&a…...
JVM基础学习
JVM分为两个子系统,两个组件一个子系统是Class loader类装载系统,另一个子系统是Execution Engine执行引擎一个组件是Runtime data area 运行时数据区,Native Interface 本地接口Class loader:根据给定的全限定类名来装载class文件到运行时数…...
ASML逆袭史:人、资金、技术,缺一不可
前言 近年来,由于众所周知的原因,荷兰ASML(阿斯麦)公司的先进半导体制造设备——光刻机,进入普通大众视野,成为人们茶余饭后谈论的焦点话题之一。 1月底,“美日荷三方谈判达成协议,可…...
MongoDB 覆盖索引查询
MongoDB 覆盖索引查询 官方的MongoDB的文档中对覆盖查询做了说明: 所有的查询字段是索引的一部分所有的查询返回字段在同一个索引中 由于所有出现在查询中的字段是索引的一部分, MongoDB 无需在整个数据文档中检索匹配查询条件和返回使用相同索引的查询…...
Flink Checkpoint 中的Aligned Checkpoint 和 Unaligned Checkpoint
文章目录知识点反压CheckpointBarrierAligned CheckpointUnaligned Checkpoint核心思想实现原理UC同步阶段UC异步阶段知识点 反压 反压是流式系统中关于处理能力的动态反馈机制,并且是从下游到上游的反馈,一般是在实时数据处理的过程中,上游…...
C++快速入门
本章内容我将结合C语言一起,初步学习了解c,与大家一起快速入门这门语言。当然鉴于c本身属于一门中级语言,大家对编程有一定了解之后来学习这门知识会更加得心应手。简介C 被认为是一种中级语言,它综合了高级语言和低级语言的特点。…...
ubuntu18.04 network有线网络图标缺失解决记录
先按照博客1安装驱动 博客1链接:Ubuntu安装 Realtek R8125 驱动_Lwang2018的博客-CSDN博客_瑞昱8125 for ubunt 安装完成后,遇到问题:ifconfig -a显示的有线网接口(名字以en开头)没有ip地址…...
java对象克隆和面向对象的设计原则
java进阶注解内置注解元注解自定义注解对象克隆浅克隆深克隆java设计模式建模语言类之间的关系依赖关系关联关系单向关联双向关联自关联聚合关系组合关系继承关系实现关系面向对象设计原则单一职责开闭原则里氏替换原则依赖倒置接口隔离迪米特原则组合/聚合复用原则注解 java注…...
传透式血氧仪设计方案
该方案一种检测方式是选择使用光敏二极管接收光信号,采用传统穿透式夹指测量;另一种是使用光谱传感器接收光信号,采用反射式测量。该传感器可将光信号直接转换成数据信息给主控端进行处理,从而节省了用户将光信号转换成模拟信号&a…...
让逆向工程师们头疼的代码混淆,就像永远也走不出的“浪浪山”
目录 代码混淆究竟是什么? 如何做代码混淆? 代码混淆不等于加密 App 加固非一时之功 “我想离开浪浪山。” 在数次尝试破解某个App 时,某个逆向工程师无奈感慨道。 逆向工程师顾名思义就是把一个个完整的软件逆推,还原成一段段…...
【拓展】基于机器学习的心脏病预测方法(14)——心脏病数据集补充
目录 前言1、数据集11.1 数据集介绍1.2 数据集属性2、数据集22.1 数据集介绍2.2 数据集属性3、数据集33.1 数据集介绍3.2 数据集属性4、下载地址前言 在实际研究过程中,前文所述数据集由于尺寸过小(仅有303份数据和13个属性信息)或数据集单一(仅有一个数据集,不具备普适性…...
深度解读Webpack中的loader原理
一、前言 webpack 是一个现代 JavaScript 应用的静态模块打包器。那么 webpack 是怎样实现不同种类资源模块加载的呢? 没错就是通过 loader。loader 用于对模块的源代码进行转换。loader 可以使你在 import 或加载模块时预处理文件。 我们带着下面几个问题&#…...
2023年全国最新二级建造师精选真题及答案
百分百题库提供二级建造师考试试题、二建考试预测题、二级建造师考试真题、二建证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关。 一、单选题 1.关于法人在建设工程中的地位的说法,正确的是(࿰…...
为什么现代企业发展离不开CRM系统的助力
如今的CRM系统对于任何企业来说都重要,因为它能帮助企业收获新客户,保留现有客户,并且将不同部门的信息全部汇集,实时提供关于每位客户整体全面的看法。因此,销售、市场营销和客户支持等领域的客户直接服务员工能够做出…...
vb.net计算之.net core基础(1)-获取农历和天气
目录 .net core 简介创建hello,world应用程序获取天气和农历.net core 简介 .NET Core是适用于 Windows、Linux 和 macOS 的免费、开源托管的计算机软件框架。 它是微软开发的第一个官方版本,具有跨平台能力的应用程序开发框架 (Application Framework),未来也将会支持 Free…...
设计模式之代理模式详解和应用
目录1 代理模式定义2 代理模式的应用场景3 代理模式的通用写法4 从静态代理到动态代理5 静态模式在业务中的应用6 动态代理在业务中的应用7 手写JDK动态代理实现原理7.1 JDK动态代理的实现原理7.2 CGLib动态代理容易踩的坑8 CGLib代理调用API及原理分析9 CGLib和JDK动态代理对比…...
JavaScript HTML DOM 节点列表
HTML DOM 是一种文档对象模型,它允许开发人员使用 JavaScript 来访问和修改网页的内容和结构。节点列表是 HTML DOM 中一个重要的概念,它允许开发人员以编程方式访问和操作文档中的节点元素。 在本文中,我们将探讨 JavaScript HTML DOM 节点…...
【音视频处理】码率、帧率越高越清晰?分辨率、像素、dpi之间是什么关系?码率的真实作用,I帧、B帧、P帧是什么
大家好,欢迎来到停止重构的频道。本期我们介绍一下视频的一些基础概念,如帧率、码率、分辨率、像素、dpi、视频帧、I帧、P帧、gop等。会解释多少码率是清晰的,是否帧率越高越流畅等问题。这些概念是比较杂乱的,我们按这样的顺序介…...
Java基础-认识注释、标识符关键字
注释 平时我们编写代码,当代码量较小时候,我们还可以看懂自己写的代码。但是当项目结构一旦复杂起来,我们就需要用到注释啦。注释并不会被执行,是写给我们开发者看的。 在java中的注释有三种 标识符 常见关键字 Java所有的组…...
【C#】静态扩展方法
静态类特征:1.不能用sealed或abstract修饰符;2.必须直接继承System.Object类型,不能试任何其他类的派生类;3.不能实现任何接口;4.不能包含任何操作符;5.不能使用protected或者protected internal修饰的静态成员&#x…...
医疗电子方案——血压计方案
高血压人群越来越多了,尤其是老人。高血压是一种十分常见的慢性疾病,同时也是引发心血管疾病最主要的因素。有关数据表明,我国每年因高血压死亡的病例竟然达到上百万之多,占到全部死亡比例的20%以上。所以大多数家庭都需要备有家用…...
深度分析React源码中的合成事件
热身准备 明确几个概念 在React17.0.3版本中: 所有事件都是委托在id root的DOM元素中(网上很多说是在document中,17版本不是了);在应用中所有节点的事件监听其实都是在id root的DOM元素中触发;React自…...
17.微服务SpringCloud
一、基本概念 Spring Cloud 被称为构建分布式微服务系统的“全家桶”,它并不是某一门技术,而是一系列微服务解决方案或框架的有序集合。它将市面上成熟的、经过验证的微服务框架整合起来,并通过 Spring Boot 的思想进行再封装,屏蔽…...
Java基础面试题——JavaWeb专题
文章目录1.HTTP响应码有哪些2.Forward和Redirect的区别?3.Get和Post请求的区别4.介绍下OSI七层和TCP/IP四层的关系5.说说TCP和UDP的区别6. 说下HTTP和HTTPS的区别7.说下HTTP、TCP、Socket的关系是什么?8. 说下HTTP的长链接和短连接的区别9.TCP原理10. Co…...
MySql数据库约束
概述、目的 概念:约束是作用于表中字段上的规则,用于限制存储在表中的数据。 目的:保证数据库中数据的正确性、有效性和完整性。 分类: 约束描述关键字非空约束限制该字段的数据不能为nullNOT NULL唯一约束保证该字段的所有数据都…...
优质的网站制作/在线网站建设平台
Sub插补X()标志X 0If余数X > Q Then余数X 余数X Mod Qx动点 x动点 1: 标志X 1EndIfEnd SubSub插补Y()标志Y 0If余数Y > Q Then余数Y 余数Y Mod Qy动点 y动点 1: 标志Y 1EndIfEnd SubSub插补Z()标志Z 0If余数Z > Q Then余数Z 余数Z Mod Qz动点 z动点 1: 标志…...
庆阳市门户网/哈尔滨seo网站管理
使用ZFPlayer过程中遇到的一些问题及解决办法参考文章: (1)使用ZFPlayer过程中遇到的一些问题及解决办法 (2)https://www.cnblogs.com/sundaysgarden/articles/9080478.html 备忘一下。...
兼职做任务赚钱的网站有哪些/最新搜索引擎排名
1638: [Usaco2007 Mar]Cow Traffic 奶牛交通 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 618 Solved: 217[Submit][Status]Description 农场中,由于奶牛数量的迅速增长,通往奶牛宿舍的道路也出现了严重的交通拥堵问题.FJ打算找出最忙碌的道路来重点整治. 这个牧区包括一个…...
平顶山建设银行网站/建站平台哪个好
Monkey简介 Monkey程序是Android系统自带,使用Java语言写成,在Android文件系统中的存放路径:/system/firmework/monkey; monkey可以运行在模拟器或实际设备中,它向系统发送伪随机的用户事件流(如按键输入、触摸屏输入和…...
网页美工设计软件/西安网站seo外包
一、简介 * 使用本地化功能,可以轻松地将应用程序翻译成多种语言,甚至可以翻译成同一语言的多种方言 * 如果要添加本地化功能,需要为每种支持的语言创建一个子目录,称为”本地化文件夹”,通常使用.lproj作为拓展名 * 当…...
防做网站视频/外贸平台排行榜前十名
原文地址 今天给客户做一个微信端的HTML5的动画页面,页面内有一个视频文件,今天上线,这是前提。刚上线不久,客户的服务器便不堪重负,为了解决问题,我们将该页面的媒体文件放在自己的服务器上。问题来了&…...