Android ViewPager缓存原理分析

易娃 等级 309 0 0

前言:

此篇文章讲述了viewpager的基本使用,以及解决和分析刷新不及时的问题,最后是项目中遇到的bug总结,希望对你们有所帮助

一.ViewPager+Fragment的使用

第一步:创建几个fragment
第二步:实例化ViewPager,添加Adapter
第三步:传值绑定

public class MainActivity extends AppCompatActivity {
    private ViewPager mViewPager;
    FragmentManager fragmentManager;
    private List<Fragment> fragments = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mViewPager = findViewById(R.id.viewPagerId);
        Fragment1 fragment1 = new Fragment1();
        Fragment2 fragment2 = new Fragment2();
        Fragment3 fragment3 = new Fragment3();
        Fragment4 fragment4 = new Fragment4();
        fragments.add(fragment1);
        fragments.add(fragment2);
        fragments.add(fragment3);
        fragments.add(fragment4);
        fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction();
        mViewPager.setAdapter(new ViewPagerAdapter(fragmentManager));
    }
public class ViewPagerAdapter extends FragmentStatePagerAdapter {

        public ViewPagerAdapter(FragmentManager fm) {
            super(fm);
        }
        @Override
        public Fragment getItem(int i) {
            return fragments.get(i);
        }

        @Override
        public int getCount() {
            return fragments.size();
        }
    } 
二.缓存原理

每次缓存一前一后和当前页面一共三个界面,当界面左边或者右边没有界面的时候,则一共缓存两个界面了。以这种方式加载pager会导致数据刷新不会即时。因为缓存中有的时候就不会从集合中拿,也就不会走生命周期的方法。
解决办法:
Android ViewPager Fragment 切换刷新数据,解决生命周期只走一次的问题

public class Fragment1 extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_fragment1, container, false);
    }

    public void onUpdate() {
        Log.d("Tina=======>", "fragment1 " + "onUpdate");
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);

        if (isVisibleToUser) {
            onUpdate();
        }

    }
} 
分析源码

在FragmentStatePagerAdapter中有一个方法setPrimaryItem,每次切换page的前后都会调用此方法,每次显示当前界面的时候总会调用fragment.setUserVisibleHint(true);因此监听setUserVisibleHint,就可以实现数据刷新了。

public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        Fragment fragment = (Fragment)object;
        if (fragment != this.mCurrentPrimaryItem) {
            if (this.mCurrentPrimaryItem != null) {
                this.mCurrentPrimaryItem.setMenuVisibility(false);
                this.mCurrentPrimaryItem.setUserVisibleHint(false);
            }

            fragment.setMenuVisibility(true);
            fragment.setUserVisibleHint(true);
            this.mCurrentPrimaryItem = fragment;
        }

    } 
三.FragmentPagerAdapter与FragmentStatePagerAdapter的区别

ViewPager中的FragmentPagerAdapter,FragmentStatePagerAdapter 缓存界面的个数是有限的,所以被挤出来的界面是要销毁掉的,FragmentPagerAdapter不会走onDestroy,所以不会完全被回收,但是FragmentStatePagerAdapter会走ondestroy彻底销毁掉。

四.Viewpager自动轮播

viewPager自动轮播的实现网上估计很多,这里的注意点发生的情景为轮播图的数量会发生变化的情况,在使用hander发送消息的时候,需要注意一点,要不然会使得项目崩溃。

 if (mHandler == null) {
            mHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    // 得到当前的页面
                    int currentItem = pager.getCurrentItem();
                    // 确定下一个页面
                    //如果轮播图为空
                    if (data.getSlider() == null || data.getSlider().isEmpty()) {
                    } else {
                        pager.setVisibility(View.VISIBLE);
                        if (currentItem < data.getSlider().size() - 1) {
                            currentItem++;
                        } else {
                            currentItem = 0;
                        }
                    }
                    // 设置页面
                    if (currentItem == 0 || data.getSlider().size() - 1 < currentItem) {
                        pager.setCurrentItem(0, false);
                    } else {
                        pager.setCurrentItem(currentItem);
                    }
                    //mScroller.setmDuration(800);
                    // 给自己发消息
                    mHandler.sendEmptyMessageDelayed(0, 3600);
                }
            };
            mHandler.sendEmptyMessageDelayed(0, 5600);
        } 

注意第19行,如果不判断currentItem是否越界,则会出现崩溃。因为,如果轮播图的个数从4减少到2,当轮播图自动滑到了第二张,此时currentItem计算完后值为2,也就是接下来会显示第三张,但是data中只有两个数据已经没有第三张了,故setCurrentItem(2)的时候,数组会发生越界,导致崩溃。
喵印~~

收藏
评论区

相关推荐

js动态生成二维码
需求:项目需要根据链接实时生成二维码,当检测终端是PC时,将当前项目链接生成二维码供用户手机端使用 判断终端是否为mobile function isMobile () { let flag navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile
Android Fragment生命周期
Fragment 是在 Android 3.0 中引入,用于解决不同屏幕分辨率的设备上 UI 显示、交互的问题。Fragment 有自己的布局,有自己的生命周期,有自己的事件响应。 但 Fragment 又是依赖于 Activity 存在的,你可以把多个 Fragment 嵌入到一个 Activity 中或者多个 Activity 重用一个 Fragmen
Android深入浅出之Binder机制
Android深入浅出之Binder机制 一 说明 Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Binder机制来和客户端通讯交互的。所以搞明白Binder的话,在很大程度上就能理解程序运行的流程。 我们这里将以MediaService的例子来分析Binder的使用: ServiceMan
移动端H5开发常用技巧总结
html 篇 常用的meta属性设置 meta对于移动端的一些特殊属性,可根据需要自行设置 <meta name"screenorientation" content"portrait" //Android 禁止屏幕旋转 <meta name"fullscreen" content"yes"             //全屏显示
Android ViewPager缓存原理分析
前言: 此篇文章讲述了viewpager的基本使用,以及解决和分析刷新不及时的问题,最后是项目中遇到的bug总结,希望对你们有所帮助 一.ViewPagerFragment的使用 第一步:创建几个fragment 第二步:实例化ViewPager,添加Adapter 第三步:传值绑定 public class MainActivity e
Android -- Fragment 基本用法、生命周期与细节注意
引言:这篇文章,大概分析下Fragment的生命周期、实际应用方法以及使用Fragment时需要注意的地方,算是Fragment的入门级文章,理解透Fragment生命周期和一些细节,就容易理解Fragment如何与外界通信等问题了。至于对其的源码分析等更加深入的内容,本文涉及不多。 Fragment的写法就不多说了,一般是继承Fragment,然后重
Android开发 常见异常和解决办法(一)
Android Studio是Android开发的理想工具,但是由于版本的更新和配置的差异,会出现很多问题,下面是以《第一行代码 第二版》为基础进行开发学习可能遇见的一些问题及其解决办法。 1.Android Studio 3.0及以上版本找不到Android Device Monitor: 解决办法: (1)在Android Studio中打开终端,如下
Django+Vue开发生鲜电商平台之4.Restful API和Vue介绍
也许今天你是最好的,但未必明天还最好;今天也许你是最差的,但社会给了你很多的机会,只要你把握,只要努力,总会有机会。 ——马云Github和Gitee代码同步更新:;。后端架构搭建好之后,需要搭建前端架构。 一、Restful API介绍 1.前后端分离优缺点近年来,随着多种平台类型(PC端、Android端、Mac端、iPhone端、P
Android AOSP基础(一)VirtualBox 安装 Ubuntu
AOSP基础 Android框架层本文首发于微信公众号「刘望舒」 前言在Android进阶三部曲第二部《Android进阶解密》的第一章,我介绍了两种阅读源码的方式,其中一种是从百度网盘:https://pan.baidu.com/s/1ngsZs 将源码下载下来,然后用SouceInsight来查看,这种方式很便捷,适合去阅读源码,但是有两个弊端,一个是无
Android无限广告轮播 - ViewPager源码分析
1.概述 这其实是我第一篇想写的博客,可能是因为我遇到了太多的坑,那个时候刚入行下了很多Demo发现怎么也改不动,可能是能力有限,这次就做一个具体的实现和彻底的封装。   上次讲了,内涵段子项目中的热吧其实还有一个广告轮播的功能没写,这里就以这个项目为例吧,附视频讲解地址:      这里写图片描述 2.ViewPager源码分析 传递数据的方式决
Android无限广告轮播 - 自定义BannerView
1.概述 这其实是我第一篇想写的博客,可能是因为我遇到了太多的坑,那个时候刚入行下了很多Demo发现怎么也改不动,可能是能力有限,这次就做一个具体的实现和彻底的封装。   上次讲了,有了源码分析我们对ViewPager就有了一个大概的了解,那么再来封装成自定义View,就会简单许多,附视频讲解地址:      这里写图片描述 2.效果封装 2.1
Android Fragment 从源码的角度去解析(下)
1.概述 上一篇博客已经简单的讲了一下Fragment的使用并写了一个基本的实例,接下来就将其整合到项目中。附视频地址:      这里写图片描述 2.效果实现 列表和轮播条不做过多的解释就是访问接口获取数据而已,这个在和都讲过了。我们直接整合进去这个时候我们发现一个奇怪的问题,就是切换之后会去重新加载数据很不正常。   一般的思路我们会换实现方法
打造炫酷通用的ViewPager指示器 - 玩转字体变色
1.概述 最近一直都在仿着其他项目的效果在做,仿内涵段子,二手车之家等等。会不会有一天被抓还真是有点心虚,我这分明是给这些APP打广告。等这些效果基本讲完就开始设计模式和系统框架一整套的视频也就会出来了,等总的访问量达到100万之后就会利用空余的时间去录制Java基础和Android基础,请各位多多start和suggest。我们来看一下效果:   
打造炫酷通用的ViewPager指示器 - Adapter模式适配所有
1.概述 上一期我们已经写了一篇 可是这种效果虽然绚烂可以装装A和C之间,但是在实际的大多数效果中并不常见,只是在内涵段子中有这个效果而已,那么这一期我们就用Adapter适配器模式适配所有的效果,堪称终结者。附视频地址:      这里写图片描述 2.效果实现 我还是还是拿上一个实例来做演示吧。这里我贴几种常见的效果,首先声明Android自带的
满满干货!高级Android都应该知道
AndroidX的前世今生Android系统在刚刚面世的时候,可能连它的设计者也没有想到它会如此成功,因此也不可能在一开始的时候就将它的API考虑的非常周全。随着Android系统版本不断地迭代更新,每个版本中都会加入很多新的API进去,但是新增的API在老版系统中并不存在,因此这就出现了一个向下兼容的问题。举个例子,当Android系统发布到3.0版本的时