从ViewPager到ViewPager2

从ViewPager到ViewPager2一、前言 之前早有耳闻 Google 为我们提供新的控件来替换老旧的 ViewPager 进而解决一些不好解决的bug问题,讲了一大堆,就是前因后果啥的…相信读者已经在“张鸿洋”大神、“郭霖”大神或者

一、前言

之前早有耳闻 Google 为我们提供新的控件来替换老旧的 ViewPager 进而解决一些不好解决的bug问题,讲了一大堆,就是前因后果啥的…相信读者已经在“张鸿洋”大神、“郭霖”大神或者是其他Android 大佬的公众号那里看见了许许多多了,或许各位感觉很无聊了,笔者菜鸟,分析不了历史背景,也不是很懂源码,但是小菜鸟,可以带给位看官尝个鲜,教你怎么用,怎么上手哈,闲话不多说,我们步入正题。

二、viewpager有2个弊端

  1. 不能关闭预加载

  2. 更新adapter不生效

    • 我们在加载数据的时候,viewpager默认会帮我们预加载前后两个页面的数据,并且这2个view是不可见的。
    • 由于viewpager对offscreenPageLimit做了限制,默认设置为1,因此页面的预加载不可避免。这也容易造成资源浪费。
    • 一般使用viewpager与frament配合使用,利用fragment的setUserVisibleHint方法,来实现控制数据懒加载。而布局只能提前进入(预布局)。

三、viewPager2离屏加载与预加载

ViewPager2预加载与离屏加载在view层面有着本质的区别,离屏加载的view已经添加到parent上,而预加载只是准备了布局,并没有加载到parent上。

  1. ViewPager2默认是开启预加载关闭离屏加载的,可能会预加载一条数据,而离屏加载即设置offscreenPageLimit为0。
  2. ViewPager2设置offscreenPageLimit为1时,在第1页会加载2条数据,每滑动一页,都会加载下一页数据,直到第五页,会移除第一页数据。

四、ViewPager2 和 ViewPager 的区别

  1. ViewPager2API最大的变化是它现在使用RecyclerView。
  2. 使用ViewPager2需要迁移到Androidx,因为android.support库中不支持ViewPager2
  3. FragmentStateAdapter替换 FragmentStatePagerAdapter
  4. RecyclerView.Adapter替代PagerAdapter
  5. registerOnPageChangeCallback 替换addPageChangeListener
  6. ViewPager2支持从右到左 (RTL) 的布局支持、垂直方向支持
  7. 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

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注