美文网首页Android开发Android技术知识Android开发经验谈
Fragment中getActivity()为空的最佳解决方案

Fragment中getActivity()为空的最佳解决方案

作者: 代码君_Coder | 来源:发表于2019-03-25 19:27 被阅读5次

    今天代码君遇到一个坑,在 Fragment 中getActivity()或getContext()返回为空,一直很懵逼,Activity都没有销毁掉,为何Activity获取会报空指针?

    实现的功能是:一个Activity 里面包含多个Fragment模块,用户自由选择Fragment模块,然后展示用户选择的模块

    实现:一个Activity+mFragmentPagerAdapter+BaseFragment ,用户选择完,更新ListFragment,然后
    刷新适配器mPagerAdapter.notifyDataSetChanged();

    一、网上资料查询

    大多数情况下的原因:你在调用了getActivity()时,当前的Fragment已经onDetach()
    了宿主Activity。比如:你在pop了Fragment之后,该Fragment的异步任务仍然在执行,并且在执行完成后调用了getActivity()方法,这样就会空指针。

    解决办法:
    在Fragment基类里设置一个Activity mActivity的全局变量,在onAttach(Activity activity)里赋值,使用mActivity代替getActivity(),保证Fragment即使在onDetach后,仍持有Activity的引用(有引起内存泄露的风险,但是相比空指针闪退,这种做法“安全”些

    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();
        }
    }
    

    二、最佳解决方案

    如果你去百度搜索,大部分是上面的答案,且不说有没有效果(实际是没效果),光是解决方案,就不是很好,因为这样持续引用,会出现内存泄漏的风险,这就是为什么国内技术资源千篇一律,都是大家互相拷贝,都不去验证有没有效果!

    下面是代码君Google的解决方案,只需要把你写的PagerAdapter继承下面的SmartFragmentStatePagerAdapter就不会出现问题

    /* 
       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);
        }
    }
    

    为何会出现空指针,大致原因是我在每次用户选择完Fragment,我都会从新new 一个Fragment,但是之前的Fragment在PagerAdapter上还存在,从而导致第二次new 的Fragment再去getActivity就为空指针了

    相关文章

      网友评论

        本文标题:Fragment中getActivity()为空的最佳解决方案

        本文链接:https://www.haomeiwen.com/subject/exjvvqtx.html