ViewPager的基本使用
ViewPager和TabLayout的使用:
https://developer.android.com/guide/navigation/navigation-swipe-view
-
PagerAdapter
主要用于加载页面是view时
可实现针对View的广告栏滑动效果
-
instantiateItem(ViewGroup, int)
创建并添加子控件,实例化控件
-
destroyItem(ViewGroup, int, Object)
判断滑动的控件是否超出了缓存范围,如果超出则销毁,移除不需要的子view控件
-
getCount()
获取viewpager要显示控件的数量
-
isViewFromObject(View, Object)
判断两个对象是否相等,是否需要重新生成子view
-
getPageTitle(int position)
设置标签页的标题
-
saveState(); finishUpdate(); getPageTitle(); getPageWidth(); registerDataSetObserver(); unregisterDataSetObserver(); startUpdate(); restoreState();
FragmentPagerAdapter与FragmentStatePagerAdapter的区别
-
-
共同点
两者都主要用于加载页面是fragment时
都是抽象类,并且都继承于PagerAdapter
使用时都要实现getItem()与getCount()两个抽象方法
-
区别
-
FragmentPagerAdapter
FragmentPagerAdapter会将每一个生成的Fragment保存在内存中,所以只适用于页面较少的情况。如果页面比较多,会导致占用较大内存,影响用户体验。
@Override public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { Fragment fragment = (Fragment) object; if (mCurTransaction == null) { mCurTransaction = mFragmentManager.beginTransaction(); } mCurTransaction.detach(fragment); if (fragment == mCurrentPrimaryItem) { mCurrentPrimaryItem = null; } }
destroyItem()中调用了detach方法,将Fragment从Activity中分离,会销毁其View,但不会销毁Fragment的实例,因此fragment还在FragmentManager的管理中,fragment所占用的资源部不会被释放。
-
FragmentStatePagerAdapter
只保留当前页面,当页面离开视线后,就会将fragment消除,释放资源,在需要fragment需要显示的时候,生成新的页面,好处是不会占用大量内存
//源码中有两个重要的变量 ArrayList<Fragment.SavedState> mSavedState; //缓存fragment的状态 ArrayList<Fragment> mFragments; //缓存fragment
如果页面不显示了,则在destroyItem()方法中将fragment从mFragments中移除,并且保存fragment的状态在mSaveState中
显示的会放入mFragments中保存
@Override public void destroyItem(ViewGroup container, int position, Object object) { Fragment fragment = (Fragment) object; if (mCurTransaction == null) { mCurTransaction = mFragmentManager.beginTransaction(); } if (DEBUG) Log.v(TAG, "Removing item #" + position + ": f=" + object + " v=" + ((Fragment)object).getView()); while (mSavedState.size() <= position) { mSavedState.add(null); } mSavedState.set(position, fragment.isAdded() ? mFragmentManager.saveFragmentInstanceState(fragment) : null); mFragments.set(position, null); mCurTransaction.remove(fragment); }
-
-
总结
FragmentPagerAdapter
适用于较少的页面,占用内存
FragmentStatePagerAdapter
适用于不确定数量,较多数量的页面时使用,大量页面时不会占用大量内存
这里需要注意一个问题,在 Fragment 没有被添加到 FragmentManager 之前,我们可以通过 Fragment.setArguments() 来设置参数,并在 Fragment 中,使用 getArguments() 来取得参数。这是常用的参数传递方式。但是这种方式对于我们说的情况不适用。因为这种数据传递方式只可能用一次,在 Fragment 被添加到 FragmentManager 后,一旦被使用,我们再次调用 setArguments() 将会导致 java.lang.IllegalStateException: Fragment already active 异常。因此,我们这里的参数传递方式选择是,在继承的 Fragment 子类中,新增几个 setter,然后通过这些 setter 将数据传递过去。反向也是类似。这些 setter 中要注意不要操作那些 View,这些 View 只有在 onCreateView() 事件后才可以操作。
@Override public Fragment getItem(int position) { MyFragment f = new MyFragment(); return f; } @Override public Object instantiateItem(ViewGroup container, int position) { MyFragment f = (MyFragment) super.instantiateItem(container, position); String title = mList.get(position); f.setTitle(title); return f; } @Override public int getItemPosition(Object object) { return PagerAdapter.POSITION_NONE; }
-
参考
https://blog.csdn.net/JSON_ZJS/article/details/78894404
https://blog.csdn.net/Jack_King007/article/details/41413405?utm_source=itdadao&utm_medium=referral
viewpager使用其他的相关参考
https://www.jianshu.com/p/f70073f7e837