Fragment和Activity在接收返回结果时的区别

        话说Fragment,每一个做过安卓开发的同学肯定都熟悉,但是如果我要问在接收返回值时,如果Fragment和Activity具有相同的请求码requestCode,他们是怎么区分的呢。

        要知道这个问题,那么我们就必须要深入源码了。其实Fragment也有相应的方法:

    public void startActivityForResult(Intent intent, int requestCode) {
        startActivityForResult(intent, requestCode, null);
    }

我们也可以在Fragment中重写onActivityResult方法:

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
    }

现在你是不是已经有点困惑了,如果我们在Activity中也重写onActivityResult方法,返回的结果到底是谁处理的呢?

    在Fragment中有两种方式:

        startActivityForResult(new Intent(mActivity, FourActivity.class),2);
        mActivity.startActivityForResult(new Intent(mActivity, FourActivity.class),2);

重点来了,其实最主要的区别就在这里,当我们在Fragment中通过第一种方式调用时,调用到了FragmentActivity的StartActivityFromFragment方法:

    public void startActivityFromFragment(Fragment fragment, Intent intent,
            int requestCode, @Nullable Bundle options) {
        mStartedActivityFromFragment = true;
        try {
            if (requestCode == -1) {
                ActivityCompat.startActivityForResult(this, intent, -1, options);
                return;
            }
            checkForValidRequestCode(requestCode);
            int requestIndex = allocateRequestIndex(fragment);
            ActivityCompat.startActivityForResult(
                    this, intent, ((requestIndex + 1) << 16) + (requestCode & 0xffff), options);//这里是重点
        } finally {
            mStartedActivityFromFragment = false;
        }
    }

看到了吧,你的requestCode已经被转化了,如果你通过第二种方式调用的话,请求码是不会被转化的,所以,就算你在Fragment和Activity中有相同的请求码,实际上也是不同的。那我们在看看返回结果的处理:

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        mFragments.noteStateNotSaved();
        int requestIndex = requestCode>>16;//看这里
        if (requestIndex != 0) {
            requestIndex--;

            String who = mPendingFragmentActivityResults.get(requestIndex);
            mPendingFragmentActivityResults.remove(requestIndex);
            if (who == null) {
                Log.w(TAG, "Activity result delivered for unknown Fragment.");
                return;
            }
            Fragment targetFragment = mFragments.findFragmentByWho(who);
            if (targetFragment == null) {
                Log.w(TAG, "Activity result no fragment exists for who: " + who);
            } else {
                targetFragment.onActivityResult(requestCode & 0xffff, resultCode, data);//看这里
            }
            return;
        }

        super.onActivityResult(requestCode, resultCode, data);
    }

当我们重写FragmentActivity的onActivityResult的时候,一定要记得调用:

super.onActivityResult(requestCode, resultCode, data);

因为返回结果必然是先让Activity接收到的,然后在super中判断请求码来自哪里。系统对于Fragment和FragmentActivity的requestCode做了处理,Fragment的处理成高16位的值,FragmentActivity的是你给的值,可能你会说,那我在FragmentActivity中的请求码是高16位的值怎么办,比如是Integer.MAX_VALUE,哈哈,我想说,你敢给,系统就敢给你抛个异常,不信请看FragmentActivity的startActivityForResult方法:

    public void startActivityForResult(Intent intent, int requestCode) {
        // If this was started from a Fragment we've already checked the upper 16 bits were not in
        // use, and then repurposed them for the Fragment's index.
        if (!mStartedActivityFromFragment) {
            if (requestCode != -1) {
                checkForValidRequestCode(requestCode);//看这里
            }
        }
        super.startActivityForResult(intent, requestCode);
    }
    static void checkForValidRequestCode(int requestCode) {
        if ((requestCode & 0xffff0000) != 0) {
            throw new IllegalArgumentException("Can only use lower 16 bits for requestCode");//看这里
        }
    }

如果你不想要异常,你还是乖一点吧。

    总结,如果你想在Fragment中处理结果就直接使用startActivityForResult方法,不要用FragmentActivity的,我们也不用担心请求码相同造成什么问题,但是一定要记住,如果你重写了FragmentActivity的onActivityResult方法时,一定要调用super的onActivityResult方法,不然你的fragment是接收不到结果的,当然如果你不嫌麻烦,自己去回调给Fragment的onActivityResult方法也行,但是系统已经实现了,我们何必多此一举呢。







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值