首页 > 编程知识 正文

android已缓存,viewpager2使用

时间:2023-05-06 02:33:44 阅读:110615 作者:4727

前言

最近,ViewPager2发布了1.0.0-版alpha 04,添加了offscreenPageLimit功能。 此功能在ViewPager中不友好。 以下是对ViewPager2的官方介绍。

众所周知,ViewPager有两个缺点。 无法关闭预加载或更新适配器。 因此,文章开头提到offscreenPageLimit在ViewPager上非常不友好。 本质上,这是因为无法将offscreenPageLimit设置为0。 如果设置为0,预加载将比想象中更关闭。

上面是ViewPager的默认加载映像,切换到当前页面时,默认情况下会在ViewPager中预加载左和右布局。 虽然看不到两边的View,但这称为预加载; 由于ViewPager对offscreenPageLimit设置了限制,页面的预加载是不可避免的。 ViewPager的源代码如下。

privatestaticfinalintdefault _ offscreen _ pages=1;

公共限制(int limit )。

不允许小于if (limit default _ offscreen _ pages )//1

log.w(tag,' requestedoffscreenpagelimit ' limit ' too small; 默认到'

DEFAULT_OFFSCREEN_PAGES;

limit=DEFAULT_OFFSCREEN_PAGES;

}

if (限制!=mOffscreenPageLimit ) {

mOffscreenPageLimit=limit;

populate (;

}

}

但是,在Fragment与ViewPager配合使用时,ViewPager强制预加载的逻辑仍然存在。 要避免预加载,请使用Fragment懒惰加载。 首先,介绍ViewPager如何与PagerAdapter配合使用以实现懒惰加载。 常用的方法如下。

实例项目(viewgroupcontainer,int position ) :初始化项目视图并返回需要添加项目视图;

estroyitem(iewgroupcontainer,int position,对象对象) :销毁ItemView并删除指定的ItemView;

isViewfromObject(viewview,对象对象):view和对象是否兼容;

setprimaryitem (viewgroupcontainer,int position,Object object ) :当前页面的主项目;

获取getcount(:item的个数

首先,说明setprimaryitem (viewgroupcontainer,int position,Object object )。 此方法指示当前页面显示了主要的Item。 什么是主要的item? 如果屏幕上绘制了预加载的ItemView,则当前主项目不会更改,除非新的ItemView已完全绘制且幻灯片已停止。 代码如下。

由于ViewPager必然会进行布局预加载,因此PagerAdapter必须先调用实例项(viewgroupcontainer,int position )方法。 instantiateitem ) )是创建ItemView的唯一方法,因此PagerAdapter的实现类FragmentPagerAdapter和FragmentStatePagerAdapter抓住此方法例如:

此外,FragmentPagerAdapter和FragmentStatePagerAdapter是instantiateItem () )进行添加或附加操作,并由预加载导致不可见的Fragment不断调用onCreate、onCreateView、onResume等方法,用户只能通过Fragment.setUserVisibleHint () )方法进行识别

大多数懒加载只能在Fragment上做手脚,结合生命周期方法和setUserVisibleHint状态,控制数据延迟加载,布局提前进入;

ViewPager2

使用ViewPager2之前,必须部署ViewPager2库。 只需在build.gradle中添加以下依赖项即可进行部署:

导入和移除

idx.viewpager2:viewpager2:1.0.0-alpha04'

然后,在布局中引入:

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() {

@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:

setAdapter() 设置适配器

setOrientation() 设置布局方向

setCurrentItem() 设置当前Item下标

beginFakeDrag() 开始模拟拖拽

fakeDragBy() 模拟拖拽中

endFakeDrag() 模拟拖拽结束

setUserInputEnabled() 设置是否允许用户输入/触摸

setOffscreenPageLimit()设置屏幕外加载页面数量

registerOnPageChangeCallback() 注册页面改变回调

setPageTransformer() 设置页面滑动时的变换效果

离屏加载

在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上;

预加载对Fragment的支持

目前,ViewPager2对Fragment的支持只能使用FragmentStateAdapter来实现,使用起来也是非常简单,例如:

默认情况下,ViewPager2是开启预加载关闭离屏加载的,这种情况下,切换页面对Fragment生命周期有何影响呢?以下是来自网络上的两个图:

问题一:关闭预加载对Fragment的影响: 经过验证,是否开启预加载,对Fragment的生命周期没有影响,结果和默认上图是一样的;

问题二:开启离屏加载对Fragment的影响: 设置offscreenPageLimit=1时:

从打印日志可以看出,offscreenPageLimit=1时,ViewPager2在第1页会加载两条数据,并且会把下一页View提前加载进来;以后每滑一页,会加载下一页数组,直到第5页,会移除第1页的Fragment;第6页会移除第2页的Fragment。

小结

针对此次的更新,ViewPager2主要有以下一些特性:

目前ViewPager2对Fragment支持只能用FragmentStateAdapter,FragmentStateAdapter在遇到预加载时,只会创建Fragment对象,不会把Fragment真正的加入到布局中,所以自带懒加载效果;

FragmentStateAdapter不会一直保留Fragment实例,回收的ItemView也会移除Fragment,所以得做好Fragment重建后恢复数据的准备;

FragmentStateAdapter在遇到offscreenPageLimit>0时,处理离屏Fragment和可见Fragment没有什么区别,所以无法通过setUserVisibleHint判断显示与否;

通过这次ViewPager2更新,官方貌似要发力替换ViewPager了,无论是它高效的复用还是自带懒加载,亦或是更新有效的Adapter,都要比ViewPager更加强大。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。