前言:
此篇文章讲述了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)的时候,数组会发生越界,导致崩溃。
喵印~~