Android ViewPager缓存原理分析

前言:

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

一.ViewPager+Fragment的使用

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

1public class MainActivity extends AppCompatActivity { 2 private ViewPager mViewPager; 3 FragmentManager fragmentManager; 4 private List<Fragment> fragments = new ArrayList<>(); 5 6 @Override 7 protected void onCreate(Bundle savedInstanceState) { 8 super.onCreate(savedInstanceState); 9 setContentView(R.layout.activity_main); 10 mViewPager = findViewById(R.id.viewPagerId); 11 Fragment1 fragment1 = new Fragment1(); 12 Fragment2 fragment2 = new Fragment2(); 13 Fragment3 fragment3 = new Fragment3(); 14 Fragment4 fragment4 = new Fragment4(); 15 fragments.add(fragment1); 16 fragments.add(fragment2); 17 fragments.add(fragment3); 18 fragments.add(fragment4); 19 fragmentManager = getSupportFragmentManager(); 20 fragmentManager.beginTransaction(); 21 mViewPager.setAdapter(new ViewPagerAdapter(fragmentManager)); 22 } 23public class ViewPagerAdapter extends FragmentStatePagerAdapter { 24 25 public ViewPagerAdapter(FragmentManager fm) { 26 super(fm); 27 } 28 @Override 29 public Fragment getItem(int i) { 30 return fragments.get(i); 31 } 32 33 @Override 34 public int getCount() { 35 return fragments.size(); 36 } 37 }
二.缓存原理

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

1public class Fragment1 extends Fragment { 2 3 @Override 4 public View onCreateView(LayoutInflater inflater, ViewGroup container, 5 Bundle savedInstanceState) { 6 return inflater.inflate(R.layout.fragment_fragment1, container, false); 7 } 8 9 public void onUpdate() { 10 Log.d("Tina=======>", "fragment1 " + "onUpdate"); 11 } 12 13 @Override 14 public void setUserVisibleHint(boolean isVisibleToUser) { 15 super.setUserVisibleHint(isVisibleToUser); 16 17 if (isVisibleToUser) { 18 onUpdate(); 19 } 20 21 } 22}
分析源码

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

1public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) { 2 Fragment fragment = (Fragment)object; 3 if (fragment != this.mCurrentPrimaryItem) { 4 if (this.mCurrentPrimaryItem != null) { 5 this.mCurrentPrimaryItem.setMenuVisibility(false); 6 this.mCurrentPrimaryItem.setUserVisibleHint(false); 7 } 8 9 fragment.setMenuVisibility(true); 10 fragment.setUserVisibleHint(true); 11 this.mCurrentPrimaryItem = fragment; 12 } 13 14 }
三.FragmentPagerAdapter与FragmentStatePagerAdapter的区别

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

四.Viewpager自动轮播

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

1 if (mHandler == null) { 2 mHandler = new Handler() { 3 @Override 4 public void handleMessage(Message msg) { 5 // 得到当前的页面 6 int currentItem = pager.getCurrentItem(); 7 // 确定下一个页面 8 //如果轮播图为空 9 if (data.getSlider() == null || data.getSlider().isEmpty()) { 10 } else { 11 pager.setVisibility(View.VISIBLE); 12 if (currentItem < data.getSlider().size() - 1) { 13 currentItem++; 14 } else { 15 currentItem = 0; 16 } 17 } 18 // 设置页面 19 if (currentItem == 0 || data.getSlider().size() - 1 < currentItem) { 20 pager.setCurrentItem(0, false); 21 } else { 22 pager.setCurrentItem(currentItem); 23 } 24 //mScroller.setmDuration(800); 25 // 给自己发消息 26 mHandler.sendEmptyMessageDelayed(0, 3600); 27 } 28 }; 29 mHandler.sendEmptyMessageDelayed(0, 5600); 30 }

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

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

swap空间的增减方法

(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )