-
简书
-
CSDN
Fragment(三)ViewPager中使用Fragment
通过这篇博客,我们能知道以下问题:
Fragment
加载到ViewPage
上的过程和用户可见性判断Fragment
加载到ViewPage2
上的过程和用户可见性判断
ViewPager
中使用 Fragment
1. Fragment
怎样加载到 ViewPage
上
使用 ViewPager
需要一个 PagerAdapter
,我们如果使用 Fragment
填充 ViewPager
的话,需要使用的是 FragmentPagerAdapter
或者 FragmentStatePagerAdapter
,当然这两个 Adapter
都是继承至 PagerAdapter
的,这两个 Adapter
有什么差别,在后面我们会说到。
对于 PagerAdapter
我们主要看三个方法 instantiateItem()
、destroyItem()
和 setPrimaryItem()
:
instantiateItem()
:创建ViewPager
页面时调用destroyItem()
:移除ViewPager
页面时调用setPrimaryItem()
:ViewPager
页面改变显示位置时调用(比如调用adapter.setCurrentItem()
方法时)
当然还有两个方法 startUpdate()
和 finishUpdate()
,分别表示将要开始改变位置和位置改变完成时调用,代码比较简单,直接看一下。就不多说了【FragmentPagerAdapter
和 FragmentStatePagerAdapter
中都一样】
@Override
public void startUpdate(@NonNull ViewGroup container) {
if (container.getId() == View.NO_ID) {
throw new IllegalStateException("ViewPager with adapter " + this
+ " requires a view id");
}
}
@Override
public void finishUpdate(@NonNull ViewGroup container) {
if (mCurTransaction != null) {
if (!mExecutingFinishUpdate) {
try {
mExecutingFinishUpdate = true;
mCurTransaction.commitNowAllowingStateLoss();
} finally {
mExecutingFinishUpdate = false;
}
}
mCurTransaction = null;
}
}
ViewPager
改变位置时的方法调用顺序
当改变 ViewPager
的位置时,方法的调用顺序为: startUpdate()
-> instantiateItem()
【ViewPager 中的 addNewItem() 方法内部调用】 -> destroyItem()
-> setPrimaryItem()
-> finishUpdate()
。
注意:因为 ViewPager
的缓存和预加载机制,instantiateItem()
和destroyItem()
方法会调用多次,并且顺序并非一个调用多次之后另一个在调用多次,而是交叉的调用。
instantiateItem()
方法解析
Fragment
加载到 ViewPage
上,主要在 instantiateItem()
方法中:
-
FragmentPagerAdapter
类// FragmentPagerAdapter 类 public Object instantiateItem(@NonNull ViewGroup container, int position) { if (mCurTransaction == null) { mCurTransaction = mFragmentManager.beginTransaction(); } final long itemId = getItemId(position); String name = makeFragmentName(container.getId(), itemId); // 当前需要显示的Fragment,是否已经存在 Fragment fragment = mFragmentManager.findFragmentByTag(name); if (fragment != null) { // 存在,调用 attach() 方法 mCurTransaction.attach(fragment); } else { // 不存在,调用 add() 方法 fragment = getItem(position); mCurTransaction.add(container.getId(), fragment, makeFragmentName(container.getId(), itemId)); } return fragment; }
先通过
FragmentManager
判断将要显示的Fragment
是否已经在容器中存在,如果存在调用FragmentTransaction#attach()
方法,否则通过getItem(position)
方法获取将要显示的Fragment
,然后调用FragmentTransaction#add()
方法将Fragment
添加到容器中。<