一、前言
之前早有耳闻 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();
}
}
4、Activity逻辑
package com.example.viewpager2.withRadioGroup;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
import android.os.Bundle;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import com.example.viewpager2.R;
public class RgActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener {
private ViewPager2 vpRg;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rg);
RgAdapter adapter = new RgAdapter(this);
RadioGroup rgVp = findViewById(R.id.rg_vp);
vpRg = findViewById(R.id.vp_rg);
rgVp.setOnCheckedChangeListener(this);
vpRg.setAdapter(adapter);
adapter.addFragment(new HomeFragment());
adapter.addFragment(new MessageFragment());
adapter.addFragment(new MyFragment());
vpRg.setCurrentItem(0);
vpRg.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
switch (position) {
case 0:
((RadioButton) findViewById(R.id.rb_home)).setChecked(true);
break;
case 1:
((RadioButton) findViewById(R.id.rb_msg)).setChecked(true);
break;
case 2:
((RadioButton) findViewById(R.id.rg_my)).setChecked(true);
break;
}
}
});
}
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.rb_home:
vpRg.setCurrentItem(0);
break;
case R.id.rb_msg:
vpRg.setCurrentItem(1);
break;
case R.id.rg_my:
vpRg.setCurrentItem(2);
break;
}
}
}
这里需要说的是 registerOnPageChangeCallback
方法 ,这个方法可以可以监听到 ViewPager 2 的界面变化,进而去操作其他的控件
六、关于DiffUtil
使用过DiffUtil都知道它的好处,没有用使用过也没有关系,听我给你说说。
- 它可以通过计算判断两个列表之间的差异进行局部刷新,而我们平时使用的
notifyDataSetChanged()
;是一个无脑刷新的操作,会刷新整个列表,对性能和视觉上并不是很友好。 - 使用差分进化算法计算更新的最小系数。
- 需要注意的是,如果你的列表数据量较大,建议在后台线程执行这个操作,DiffResult默认在主线程中执行。
- 如果启用了移动检测,则需要花费额外的o(N ^2)时间,其中N是已添加和已删除项目的总数。如果您的列表已经按相同的约束排序(例如,为帖子列表创建的时间戳),则可以禁用移动检测以提高性能。
今天的文章从ViewPager到ViewPager2分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/21163.html