今天代碼君遇到一個(gè)坑,在 Fragment 中g(shù)etActivity()或getContext()返回為空焙糟,一直很懵逼,Activity都沒有銷毀掉迫卢,為何Activity獲取會(huì)報(bào)空指針虏等?
實(shí)現(xiàn)的功能是:一個(gè)Activity 里面包含多個(gè)Fragment模塊挤渐,用戶自由選擇Fragment模塊蝠引,然后展示用戶選擇的模塊
實(shí)現(xiàn):一個(gè)Activity+mFragmentPagerAdapter+BaseFragment 轻绞,用戶選擇完搏嗡,更新ListFragment窿春,然后
刷新適配器mPagerAdapter.notifyDataSetChanged();
一、網(wǎng)上資料查詢
大多數(shù)情況下的原因:你在調(diào)用了getActivity()時(shí)采盒,當(dāng)前的Fragment已經(jīng)onDetach()
了宿主Activity旧乞。比如:你在pop了Fragment之后,該Fragment的異步任務(wù)仍然在執(zhí)行磅氨,并且在執(zhí)行完成后調(diào)用了getActivity()方法尺栖,這樣就會(huì)空指針。
解決辦法:
在Fragment基類里設(shè)置一個(gè)Activity mActivity的全局變量烦租,在onAttach(Activity activity)里賦值延赌,使用mActivity代替getActivity(),保證Fragment即使在onDetach后叉橱,仍持有Activity的引用(有引起內(nèi)存泄露的風(fēng)險(xiǎn)挫以,但是相比空指針閃退,這種做法“安全”些
public class BaseFragment extends Fragment {
private Activity activity;
public Context getContext() {
if (activity == null) {
return MyApplication.getInstance();
}
return activity;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
activity = getActivity();
}
}
二窃祝、最佳解決方案
如果你去百度搜索掐松,大部分是上面的答案,且不說有沒有效果(實(shí)際是沒效果)粪小,光是解決方案甩栈,就不是很好,因?yàn)檫@樣持續(xù)引用糕再,會(huì)出現(xiàn)內(nèi)存泄漏的風(fēng)險(xiǎn)量没,這就是為什么國(guó)內(nèi)技術(shù)資源千篇一律,都是大家互相拷貝突想,都不去驗(yàn)證有沒有效果殴蹄!
下面是代碼君Google的解決方案究抓,只需要把你寫的PagerAdapter繼承下面的SmartFragmentStatePagerAdapter就不會(huì)出現(xiàn)問題
/*
Extension of FragmentStatePagerAdapter which intelligently caches
all active fragments and manages the fragment lifecycles.
Usage involves extending from SmartFragmentStatePagerAdapter as you would any other PagerAdapter.
*/
public abstract class SmartFragmentStatePagerAdapter extends FragmentStatePagerAdapter {
// Sparse array to keep track of registered fragments in memory
private SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
public SmartFragmentStatePagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
// Register the fragment when the item is instantiated
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
// Unregister when the item is inactive
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
// Returns the fragment for the position (if instantiated)
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
}
為何會(huì)出現(xiàn)空指針,大致原因是我在每次用戶選擇完Fragment袭灯,我都會(huì)從新new 一個(gè)Fragment刺下,但是之前的Fragment在PagerAdapter上還存在,從而導(dǎo)致第二次new 的Fragment再去getActivity就為空指針了