'FragmentHostCallback.getHandler()' on a null object reference

Attempt to invoke virtual method ‘android.os.Handler android.support.v4.app.FragmentHostCallback.getHandler()’ on a null object reference

最近写的一个动态权限库中用到了Fragment进行权限的请求和管理,但是在上线后发现bugly爆了一个null指针的问题闲来没事就去跟了跟源码

想对Fragment有更深入了解的点这里哦:Fragment 和 Activity 关联源码梳理

出错的本地代码
            rxPermissionsFragment = RxPermissionsFragment()
            fragmentManager
                    .beginTransaction()
                    .add(rxPermissionsFragment, TAG)
                    .commitNowAllowingStateLoss() //这一行
bugly上显示的出错堆栈

android.support.v4.app.FragmentManagerImpl.ensureExecReady(TbsSdkJava:1959)

可以看出来是FragmentManager中的ensureExecReady()方法。定位到该方法:

    /**
     * Broken out from exec*, this prepares for gathering and executing operations.
     *
     * @param allowStateLoss true if state loss should be ignored or false if it should be
     *                       checked.
     */
    private void ensureExecReady(boolean allowStateLoss) {
        if (mExecutingActions) {
            throw new IllegalStateException("FragmentManager is already executing transactions");
        }
				
				//注意这一行
        if (Looper.myLooper() != mHost.getHandler().getLooper()) {
            throw new IllegalStateException("Must be called from main thread of fragment host");
        }

        if (!allowStateLoss) {
            checkStateLoss();
        }

        if (mTmpRecords == null) {
            mTmpRecords = new ArrayList<>();
            mTmpIsPop = new ArrayList<>();
        }
        mExecutingActions = true;
        try {
            executePostponedTransaction(null, null);
        } finally {
            mExecutingActions = false;
        }
    }

发现是由于mHost.getHandler().getLooper()出现了空指针,接下来去定位到mHost的初始化和销毁的方法:

    public void dispatchDestroy() {
        mDestroyed = true;
        execPendingActions();
        mExecutingActions = true;
        moveToState(Fragment.INITIALIZING, false);
        mExecutingActions = false;
        mHost = null;
        mContainer = null;
        mParent = null;
    }

发现实际上就是在Fragment的onDestroy中会调用,再往上看发现会在Activity的onDestroy中进行调用。

结论

根据上面的源码追踪,最终造成这个异常的原因就是当调用FragmentManager的commitNowAllowingStateLoss()时该Fragment的关联Activity已经调用过onDestroy,也就是已经被销毁。

解决方案

在调用commitNowAllowingStateLoss()之前判断FragmentManager的状态,如:

       //避免异常情况下Activity被销毁后继续调用导致异常
        if (fragmentManager.isDestroyed) {
            return null
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值