Fragment中g(shù)etActivity()為空的最佳解決方案

今天代碼君遇到一個(gè)坑,在 Fragment 中g(shù)etActivity()或getContext()返回為空,一直很懵逼,Activity都沒(méi)有銷毀掉,為何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();
    }
}

二、最佳解決方案

如果你去百度搜索,大部分是上面的答案,且不說(shuō)有沒(méi)有效果(實(shí)際是沒(méi)效果),光是解決方案,就不是很好,因?yàn)檫@樣持續(xù)引用,會(huì)出現(xiàn)內(nèi)存泄漏的風(fēng)險(xiǎn),這就是為什么國(guó)內(nèi)技術(shù)資源千篇一律,都是大家互相拷貝,都不去驗(yàn)證有沒(méi)有效果!

下面是代碼君Google的解決方案,只需要把你寫的PagerAdapter繼承下面的SmartFragmentStatePagerAdapter就不會(huì)出現(xiàn)問(wè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就為空指針了

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容