技术标签: android高级开发
最近ViewPager2发布了1.0.0-alpha04版本,新增offscreenPageLimit功能,该功能在ViewPager上并不友好,以下是官方对于ViewPager2的介绍:
众所周知,ViewPager有两个毛病:不能关闭预加载和更新Adapter不生效
,所以开头我为什么说offscreenPageLimit在ViewPager上十分不友好;本质上是因为offscreenPageLimit不能设置成0(设置成0就是想象中的关闭预加载)。
上面是ViewPager默认情况下的加载示意图,当切换到当前页面时,会默认预加载左右两侧的布局到ViewPager中,尽管两侧的View并不可见的,我们称这种情况叫预加载;由于ViewPager对offscreenPageLimit设置了限制,页面的预加载是不可避免。ViewPager的源码如下:
private static final int DEFAULT_OFFSCREEN_PAGES = 1;
public void setOffscreenPageLimit(int limit) {
if (limit < DEFAULT_OFFSCREEN_PAGES) {//不允许小于1
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强制预加载的逻辑在Fragment配合ViewPager使用时依然存在。为了不进行预加载,可以使用Fragment懒加载。先说一下ViewPager配合PagerAdapter实现懒加载的方法,常用的有以下几个方法:
先说setPrimaryItem(ViewGroup container, int position, Object object),该方法表示当前页面正在显示主要Item,何为主要Item?如果预加载的ItemView已经划入屏幕,当前的PrimaryItem依然不会改变,除非新的ItemView完全划入屏幕,且滑动已经停止才会判断,涉及代码如下:
由于ViewPager不可避免的进行布局预加载,造成PagerAdapter必须提前调用instantiateItem(ViewGroup container, int position)方法,instantiateItem()是创建ItemView的唯一入口方法,所以PagerAdapter的实现类FragmentPagerAdapter和FragmentStatePagerAdapter必须抓住该方法进行Fragment对象的创建。例如:
需要说明的是,FragmentPagerAdapter和FragmentStatePagerAdapter一股脑的在instantiateItem()中进行创建且进行add或attach操作,并没有在setPrimaryItem()方法中对Fragment进行操作。因此,预加载会导致不可见的Fragment一股脑的调用onCreate、onCreateView、onResume等方法,用户只能通过Fragment.setUserVisibleHint()方法进行识别。
大多数的懒加载都是对Fragment做手脚,结合生命周期方法和setUserVisibleHint状态,控制数据延迟加载,而布局只能提前进入;
使用ViewPager2之前,需要先引入ViewPager2库,引入时只需要在build.gradle添加如下依赖即可:
implementation 'androidx.viewpager2:viewpager2:1.0.0-alpha04'
然后,在布局中引入:
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
ViewPager2可以和Adapter一起使用,也可以和Fragment一起使用。
ViewPager2 viewPager = findViewById(R.id.view_pager2);
viewPager.setAdapter(new RecyclerView.Adapter<ViewHolder>() {
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_card_layout, parent, false);
ViewHolder viewHolder = new ViewHolder(itemView);
return viewHolder;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.labelCenter.setText(String.valueOf(position));
}
@Override
public int getItemCount() {
return SIZE;
}
}));
static class ViewHolder extends RecyclerView.ViewHolder{
private final TextView labelCenter;
public ViewHolder(@NonNull View itemView) {
super(itemView);
labelCenter = itemView.findViewById(R.id.label_center);
}
}
当然,ViewPager2也可以和Fragment配合使用。
viewPager.setAdapter(new FragmentStateAdapter(this) {
@NonNull
@Override
public Fragment getItem(int position) {
return new VSFragment();
}
@Override
public int getItemCount() {
return SIZE;
}
});
ViewPager2和ViewPager在使用方式上差不多,主要有以下一些API:
在1.0.0-alpha04版本中,ViewPager2提供了离屏加载功能,该功能和ViewPager的预加载存的的意义似乎是一样的。
public static final int OFFSCREEN_PAGE_LIMIT_DEFAULT = 0;
public void setOffscreenPageLimit(int limit) {
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;
// Trigger layout so prefetch happens through getExtraLayoutSize()
mRecyclerView.requestLayout();
}
为了方便分析ViewPager2和ViewPager的区别,我们看一下布局方面的对比:
为了对比两者加载布局的效果,我准备了LinearLayout同时展示ViewPager和ViewPager2,设置相同的Item布局和数据源,然后用Android布局分析工具抓取两者的布局结构,效果如下:
从分析结果来看,ViewPager会默认会预布局两侧各一个布局,ViewPager2默认不进行预布局,主要由各自的默认offscreenPageLimit参数决定,ViewPager默认为1且不允许小于1,ViewPager2默认为0。
分析运行结果,在设置相同的offscreenPageLimit时,两者都会预布局左右(上下)两者的offscreenPageLimit个ItemView;
从对比结果上来看,ViewPager2的offscreenPageLimit和ViewPager运行结果一样,但是ViewPager2最小offscreenPageLimit可以设置为0;
ViewPager2预加载即RecyclerView的预加载,代码在RecyclerView的GapWorker中。ViewPager2会默认开启预加载,表现形式是在拖动控件或者Fling时,可能会预加载一条数据;下面是预加载的示意图:
如果要关闭预加载,可以使用下面的代码:
((RecyclerView)viewPager.getChildAt(0)).getLayoutManager().setItemPrefetchEnabled(false);
预加载的开关在LayoutManager上,只需要获取LayoutManager并调用setItemPrefetchEnabled()即可控制开关;
ViewPager2默认会缓存2条ItemView,而且在最新的RecyclerView中可以自定义缓存Item的个数,方法如下:
public void setItemViewCacheSize(int size) {
mRecycler.setViewCacheSize(size);
}
预加载和缓存在View层面没有本质的区别,都是已经准备了布局,但是没有加载到parent视图上; 预加载和离屏加载在View层面有本质的区别,离屏加载的View已经添加到parent上;
目前,ViewPager2对Fragment的支持只能使用FragmentStateAdapter来实现,使用起来也是非常简单,例如:
默认情况下,ViewPager2是开启预加载关闭离屏加载的,这种情况下,切换页面对Fragment生命周期有何影响呢?以下是来自网络上的两个图:
问题一:关闭预加载对Fragment的影响: 经过验证,是否开启预加载,对Fragment的生命周期没有影响,结果和默认上图是一样的;
问题二:开启离屏加载对Fragment的影响: 设置offscreenPageLimit=1时:
从打印日志可以看出,offscreenPageLimit=1时,ViewPager2在第1页会加载两条数据,并且会把下一页View提前加载进来;以后每滑一页,会加载下一页数组,直到第5页,会移除第1页的Fragment;第6页会移除第2页的Fragment。
针对此次的更新,ViewPager2主要有以下一些特性:
通过这次ViewPager2更新,官方貌似要发力替换ViewPager了,无论是它高效的复用还是自带懒加载,亦或是更新有效的Adapter,都要比ViewPager更加强大。
TypeScript简介1、TypeScript的作者是安德斯·海尔斯伯格,C#的首席架构师。2012年10月,微软发布了首个公开版本的TypeScript,2013年6月19日,在经历了一个预览版之后微软正式发布了正式版TypeScript,是由微软开发的开源、跨平台的编程语言。2、TypeScript是为大型应用的开发而设计,并且可以编译为JavaScript。3、TypeScript 是 JavaScript 的一个超集,TypeScript扩展了JavaScript的语法,任何现有的Java
从github上导项目到本地的时候,前端项目报错。这是因为vue的版本和vue-template-compiler的版本不一致导致的,我看网上有的解决办法是执行以下命令npm install [email protected] --save我试了没有成功,我的解决方案是把packag.json改成和上面的版本号一致就可以了...
1. 下载题目链接下载题目给出的.pyc文件。2. 具体分析pyc 是一种二进制文件,是由py文件经过编译后,生成的文件,是一种byte code,py文件变成pyc文件后,加载的速度有所提高,而且pyc是一种跨 平台的字节码,是由python的虚拟机来执行的,这个是类似于JAVA或者.NET的虚拟机的概念。pyc的内容,是跟python的版本相关的,不同 版本编译后的pyc文件是不同的,2.5编译的pyc文件,2.4版本的python是无法执行的。3. 反汇编在线查找python反汇编
本来是想找一道生成树的题做的...结果被洛咕的标签骗到了这题...结果是二分答案与生成树一点mao关系都没有....题目大意:给你一个序列,请你删去某一个$l~r$区间的值($2<=i<=j<=n-1$),使得剩余元素的平均值最小。开始是想二分序列长度的,后来发现没什么卵用。。。于是再想一想二分平均值,但是又感觉并没有二分单调性...(其实是满足的,因为我们二分...
hdu 4196 Remoteland点击做题网站链接题目描述Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Problem DescriptionIn the Republic of Remoteland, the people celebrate their inde...
因为安装的时候没有截图,所以,只有文字描述了。执行以下几条命令apt-get updateapt-get install ubuntu-desktop后面一条语句的运行过程中,需要两次手动输入y...
upd2:D2T2忘记特判小数据丢了10分。。。总分100+100+100+72+55+44=471upd1:代码下发了,重测了民间成绩,静等11.19出官方成绩 以及:代码全部改为考场代码 Day1:原题大赛,水题大联欢,服了希望Day2不是爆零赛T1:铺设道路这差分一下不就是sb题了吗复杂度#include&lt;bit...
Caffe源码中各种依赖库的作用及简单使用!
一、原理_频率域平滑理想低通滤波器的传递函数为:n 阶巴特沃斯低通滤波器的传递函数为:n 阶指数低通滤波器的传递函数为:二、步骤(1)读入原图像test.tif并显示;(2)对原图像添加高斯噪声;(3)采用理想低通滤波器对加噪图像滤波,并显示滤波结果;观察截止频率 D0 分别为15、30、80时,理想低通滤波的结果。(4)采用二阶巴特沃斯低通滤波器对加噪图像滤波,并显示滤波结果;观察截止频率 D0 分别为15、30、80时,二阶巴特沃斯低通滤波的结果。(5)采用二阶指数低通滤波器
6月25日,百度地图在北京举行了“好住计划”发布会,宣布将依托先进的AI技术,推进地图应用与社会经济各领域的深度融合。一、暖心的百度地图 “好住计划”百度地图这次发布的“好住计划”,顾名思义就是以用户的居住以及通勤,等实际需求为核心的应用计划。在功能上,好住计划主要以“通勤租房”和“商旅酒店”两大产品,为用户在不可或缺的找房、出行住宿等场景下,提供更好的体验。发布会上,百度地图方面表示该计划将与贝壳、安居客、携程、同程等居住和通勤领域的头部平台无缝合作,实现技术、平台与产业的融合创新,让用户能够
以百度新闻为例,介绍如何基于HttpClient去采集网络新闻资源信息。
Shell Sort is a generalization of Insertion Sort to arrange a list of nn elements AA .1 insertionSort(A, n, g)2 for i = g to n-13 v = A[i]4 j = i - g5 while j &...