Android ViewPager缓存原理分析

易娃 等级 631 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)的时候,数组会发生越界,导致崩溃。
喵印~~

收藏
评论区

相关推荐

Android ViewPager缓存原理分析
前言: 此篇文章讲述了viewpager的基本使用,以及解决和分析刷新不及时的问题,最后是项目中遇到的bug总结,希望对你们有所帮助 一.ViewPagerFragment的使用 第一步:创建几个fragment 第二步:实例化ViewPager,添加Adapter 第三步:传值绑定 public class MainActivity e
Android -- Fragment 基本用法、生命周期与细节注意
引言:这篇文章,大概分析下Fragment的生命周期、实际应用方法以及使用Fragment时需要注意的地方,算是Fragment的入门级文章,理解透Fragment生命周期和一些细节,就容易理解Fragment如何与外界通信等问题了。至于对其的源码分析等更加深入的内容,本文涉及不多。 Fragment的写法就不多说了,一般是继承Fragment,然后重
Android Fragment 从源码的角度去解析(下)
1.概述 上一篇博客已经简单的讲了一下Fragment的使用并写了一个基本的实例,接下来就将其整合到项目中。附视频地址:      这里写图片描述 2.效果实现 列表和轮播条不做过多的解释就是访问接口获取数据而已,这个在和都讲过了。我们直接整合进去这个时候我们发现一个奇怪的问题,就是切换之后会去重新加载数据很不正常。   一般的思路我们会换实现方法
Android之ActionBar、Tabs、Fragment、ViewPager实现标签页切换并缓存页面
感觉 Android 到处都是坑,每个地方都要把人折腾半天。 今天来简单说说 Android之ActionBar、Tabs、Fragment、ViewPager 实现标签页切换并缓存页面 关于他们的介绍就不多说了,网上到处都是,只说关键的部分: 我在开发的时候遇到几个疑难问题,花费大量时间处理,总结如下: 1\. 关于 Fragment 内部逻辑处理
ViewPager+Fragment滑动界面,并做延迟加载
**本代码有缺陷,如果回到桌面后,资源被系统回收后会报错。 新文章: [http://blog.csdn.net/q445697127/article/details/18352033](https://www.oschina.net/action/GoToLink?url=http%3A%2F%2Fblog.csdn.net%2Fq445697127%
QQ最新版布局猜想
最近想实现类似QQ的布局,使用toolbar,tablayout,viewpager,drawerlayout等控件,碰到了一些问题。 1. 底部按钮切换之后,每个页面头部布局不一样。使用toolbar的话,需要在每个fragment中使用单独的toolbar。这样又出现一个新的问题,drawerlayout如何操作,drawerlayout需要
ViewPager+TabLayout+Fragment刷新Fragment中的数据
1.ViewPager与TabLayout的初始化: 1 private void initData() { 2 mTabFragmentAdapter = new TabFragmentFirstAdapter(getSupportFragmentManager(), mDeptType); 3 m
ViewPager不为人知的秘密
假如你要做一个ViewPager翻页的控制,在某种情况下能够翻页、在某种情况下又不允许翻页,你该如何去做呢? 本文就提供了VIewPager的这些不为人知的秘密~~: http://www.jianshu.com/p/80891d0185f7 同步发布在CSDN: http://blog.csdn.net/eclipsexys/a
viewpager 和滑动条同步滚动
实现上面的radiobutton和viewpager同步滚动太过复杂,请直接使用开源项目[PagerSlidingTabStrip](http://my.oschina.net/sldk/blog/402638) 共有6个的页面,导航栏用horizontalscrollview封装radiogroup。点击radiobutton跳转到对应的页面。滑动p
Android 解决ViewPager双层嵌套的滑动问题
原文地址 h[ttps://www.cnblogs.com/zhujiabin/p/7083290.html](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.cnblogs.com%2Fzhujiabin%2Fp%2F7083290.html) 之前在做自己的一个项目的时候,遇到
Android客户端图片左右滑动(自动切换)
本例是用ViewPager去做的实现,支持自动滑动和手动滑动,不仅优酷网,实际上有很多商城和门户网站都有类似的实现: 具体思路: 1\. 工程中需要添加android-support-v4.jar,才能使用ViewPager控件. 2\. 图片的自动切换: 可使用Timer或者ScheduledExecutorService,这个有多重方式可以实现.
Android开源控件ViewPager Indicator的使用方法
Android Viewpager Indicator是Android开发中最常用的控件之一,几乎所有的新闻类APP中都有使用,下面介绍其基本使用方法。 ![](http://static.oschina.net/uploads/img/201403/14220432_afb0.png) ### **1\. ViewPager Indicator的Lib
Android开源项目分类汇总
第一部分 个性化控件(View) ---------------- 主要介绍那些不错个性化的View,包括ListView、ActionBar、Menu、ViewPager、Gallery、 GridView、ImageView、ProgressBar、TextView、ScrollView、TimeView、TipView、 FlipView、Color
NestedScrollView 嵌套ViewPageer,ViewPager中嵌套多个带RecyclerView的自定义view滑动时的问题解决
遇到的问题描述: 嵌套后ViewPager中的view展示不出来,解决办法:重新设置Viewpager的高度 自定义viewpager public class WrapViewPager extends ViewPager { private int current; private int heig
TabLayout 的几种用法
### 1.结合ViewPager使用 这是最常见的用法了,实现也比较简单。 ![tablayout01.gif](https://upload-images.jianshu.io/upload_images/1354448-c52cde3a668e998a.gif?imageMogr2/auto-orient/strip) 布局文件: