前言
之前早有耳闻 Google 为我们提供新的控件来替换老旧的 ViewPager 进而解决一些不好解决的bug问题,讲了一大堆,就是前因后果啥的…相信读者已经在“张鸿洋”大神、“郭霖”大神或者是其他Android 大佬的公众号那里看见了许许多多了,或许各位感觉很无聊了,笔者菜鸟,分析不了历史背景,也不是很懂源码,但是小菜鸟,可以带给位看官尝个鲜,教你怎么用,怎么上手哈,闲话不多说,我们步入正题。
viewpager有2个弊端
不能关闭预加载
更新adapter不生效
我们在加载数据的时候,viewpager默认会帮我们预加载前后两个页面的数据,并且这2个view是不可见的。
由于viewpager对offscreenPageLimit做了限制,默认设置为1,因此页面的预加载不可避免。这也容易造成资源浪费。
一般使用viewpager与frament配合使用,利用fragment的setUserVisibleHint方法,来实现控制数据懒加载。而布局只能提前进入(预布局)。
viewPager2离屏加载与预加载
ViewPager2的预加载与离屏加载在view层面有着本质的区别,离屏加载的view已经添加到parent上,而预加载只是准备了布局,并没有加载到parent上。
- ViewPager2默认是开启预加载关闭离屏加载的,可能会预加载一条数据,而离屏加载即设置offscreenPageLimit为0。
- ViewPager2设置offscreenPageLimit为1时,在第1页会加载2条数据,每滑动一页,都会加载下一页数据,直到第五页,会移除第一页数据
ViewPager2 和 ViewPager 的区别
- ViewPager2API最大的变化是它现在使用RecyclerView。
- 使用ViewPager2需要迁移到Androidx,因为android.support库中不支持ViewPager2
- FragmentStateAdapter替换 FragmentStatePagerAdapter
- RecyclerView.Adapter替代PagerAdapter
- registerOnPageChangeCallback 替换addPageChangeListener
- ViewPager2支持从右到左 (RTL) 的布局支持、垂直方向支持
- ViewPager2支持停用用户输入的功能(setUserInputEnabled、isUserInputEnabled)
简单使用
1、引入依赖
implementation 'androidx.viewpager2:viewpager2:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0' // ViewPager 2 需要使用 RecycleView 的 adapter
2、xml布局
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/vp_rg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/rg_vp" />
3、Adapter
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import java.util.ArrayList;
import java.util.List;
/**
* CreateTime: 2021/10/30 21:32
* Author: iwen大大怪
*/
public class RgAdapter extends FragmentStateAdapter {
private List<Class> fragments;
public RgAdapter(@NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
if (fragments == null) {
fragments = new ArrayList<>();
}
}
public void addFragment(Fragment fragment) {
if (fragments != null) {
fragments.add(fragment.getClass());
}
}
@NonNull
@Override
public Fragment createFragment(int position) {
try {
return (Fragment) fragments.get(position).newInstance();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return null;
}
@Override
public int getItemCount() {
return fragments.size();
}
}
这里需要说的是 registerOnPageChangeCallback 方法 ,这个方法可以可以监听到 ViewPager 2 的界面变化,进而去操作其他的控件
关于DiffUtil
使用过DiffUtil都知道它的好处,没有用使用过也没有关系,听我给你说说。
它可以通过计算判断两个列表之间的差异进行局部刷新,而我们平时使用的notifyDataSetChanged();是一个无脑刷新的操作,会刷新整个列表,对性能和视觉上并不是很友好。
使用差分进化算法计算更新的最小系数。
需要注意的是,如果你的列表数据量较大,建议在后台线程执行这个操作,DiffResult默认在主线程中执行。
如果启用了移动检测,则需要花费额外的o(N ^2)时间,其中N是已添加和已删除项目的总数。如果您的列表已经按相同的约束排序(例如,为帖子列表创建的时间戳),则可以禁用移动检测以提高性能。