Android 保存Fragment 引用及 getActivity() 为空问题

问题分析:

在使用Fragment的时候经常会遇到getActivity()为null的情况。比如我在一个异步网路请求的回调中调用了getActivity()就会出现空指针问题。之前解决这个问题,通常都是直接加空指针判断来规避,但是这并没有真正解决问题。

很多人都曾被这个问题所困扰,如果app长时间在后台运行,再次进入app的时候可能会出现crash,而且fragment会有重叠现象。如果系统内存不足、切换横竖屏、app长时间在后台运行,Activity都可能会被系统回收然后重建,但Fragment并不会随着Activity的回收而被回收,创建的所有Fragment会被保存到Bundle里面,从而导致Fragment丢失对应的Activity。

下面是FragmentActivity的部分源码

 protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Parcelable p = mFragments.saveAllState();
        if (p != null) {
            outState.putParcelable( "android:support:fragments", p);
        }
    }

如果从最近使用的应用里面点击应用,系统会恢复之前被回收的Activity,这个时候FragmentActivity在oncreate里面也会恢复Bundle里的Fragment

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        mFragments.attachActivity(this, mContainer, null);
        // Old versions of the platform didn't do this!
        if (getLayoutInflater().getFactory() == null) {
            getLayoutInflater().setFactory(this);
        }
        super.onCreate(savedInstanceState);      
        NonConfigurationInstances nc = (NonConfigurationInstances)
                getLastNonConfigurationInstance();
        if (nc != null) {
            mAllLoaderManagers = nc.loaders;
        }
        if (savedInstanceState != null) {
            Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
            mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
        }
        mFragments.dispatchCreate();
    }

重现步骤:

假设一个页面叫MyActivity(继承自FragmentActivity),其中用到的Fragment叫MyFragment。

出现上面这种情况时,app发生的变化如下:

1、在前面提到的几种情况下系统回收了MyActivity

2、通过onSaveInstanceState保存MyFragment的状态

3、用户再次点击进入app

4、由于MyActivity被回收,系统会重启MyActivity,根据之前在Bundle保存的MyFragment的状态恢复Fragment

5、MyActivity的代码逻辑中,会再次创建新的MyFragment

6、页面出现混乱,覆盖了两层的fragment。假如恢复的MyFragment使用到了getActivity()方法,会报空指针异常

解决办法:

对于上面的问题,考虑下面这两种:

1、不保存fragment的状态:在MyActivity中重写onSaveInstanceState方法,将super.onSaveInstanceState(outState);注释掉,让其不再保存Fragment的状态,达到fragment随MyActivity一起销毁的目的。

2、重建时清除已经保存的fragment的状态:在恢复Fragment之前把Bundle里面的fragment状态数据给清除。方法如下:

if(savedInstanceState!= null) {
     String FRAGMENTS_TAG =  "android:support:fragments";
     savedInstanceState.remove(FRAGMENTS_TAG);
}

参考:

Android 保存 Fragment 引用及 getActivity() 为空问题
Fragment中调用getActivity为null的问题
解决在Fragment中getActivity()为空问题
关于Activity被回收,Fragment还在的问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值