現在對處理viewpager、fragment使用過程中的回收問題,做一下記錄
首先看下初始化fragment初始化的代碼,對成員變量FragmentA、fragmentB進行賦值,並設置viewpager的adapter
僞代碼:
private void initFragment() {
mFragmentA = FragmentA.newInstance();
mFragmentB = FragmentB.newInstance();
fragments = new ArrayList<>();
fragments.add(mFragmentA);
fragments.add(mFragmentB);
mFragmentAdapter = new HomeFragmentAdapter(this,fragments);
mViewPager.setAdapter(mFragmentAdapter);
}
再看fragmentPagerAdapter源碼
在對fragment綁定的時候,會先findFragmentByTag,如果之前有被回收的fragment,會進行復用,也就是說不會執行新生成的fragment.attach(),相當於新的fragment是沒有用的,但是我們的成員變量指向的確實這個新生成的fragment。
@Override public Object instantiateItem(ViewGroup container, int position) { if (mCurTransaction == null) { mCurTransaction = mFragmentManager.beginTransaction(); } final long itemId = getItemId(position); // Do we already have this fragment? String name = makeFragmentName(container.getId(), itemId); Fragment fragment = mFragmentManager.findFragmentByTag(name); if (fragment != null) { if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment); mCurTransaction.attach(fragment); } else { fragment = getItem(position); if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment); mCurTransaction.add(container.getId(), fragment, makeFragmentName(container.getId(), itemId)); } if (fragment != mCurrentPrimaryItem) { fragment.setMenuVisibility(false); fragment.setUserVisibleHint(false); } return fragment; }
解決:在onRestoreInstance當中對舊的fragment重新引用
示意代碼:
@Override public void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); Fragment fragmentFirst = getSupportFragmentManager().findFragmentByTag(makeFragmentName(mViewPager.getId(), 0)); if (fragmentFirst != null) { mFragmentA = (FragmentA) fragmentFirst; } Fragment fragmentSecond = getSupportFragmentManager().findFragmentByTag(makeFragmentName(mViewPager.getId(), 1)); if (fragmentSecond != null) { mFragmentB= (FragmentB)fragmentSecond; } } /** * 參考fragmentPagerAdapter中的尋找fragment的方法 */ private static String makeFragmentName(int viewId, long id) { return "android:switcher:" + viewId + ":" + id; }