美文网首页Android开发技术分享Android知识Android技术知识
Fragment的onActivityResult方法为什么有的

Fragment的onActivityResult方法为什么有的

作者: 珠穆朗玛小王子 | 来源:发表于2018-01-24 17:33 被阅读0次

    #前言

    还有20天就要过年了,心情非常的激动,感觉自己已经要膨胀了,所以今天来讨论一下两个比较常见的问题,相信很多朋友都已经研究过了,不过年底了就当是复习了吧。

    现在我们开始讨论今天的话题

    (PS:请注意,我用的kotlin,并不是Java,但是我相信Java同学肯定看的懂)

    #Fragment的onActivityResult方法

    最近新项目里有这样一个使用场景:

    在Activity里,嵌套了一个Fragment,这个Fragment用来从手机中选择照片。

    val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
    startActivityForResult(Intent.createChooser(intent, resources.getString(R.string.please_select_pic)), REQUEST_PICK)

    写法还是很简单的,很幸运,我发现Fragment也是有onActivityResult方法,于是按照平时的套路写完了代码,结果非常成功。

    紧接着,出现了另一个需求:

    编辑用户昵称,跳转到一个编辑Activity,返回显示新的用户昵称。

    于是我满怀希望的按照刚才的套路写了一遍代码:

    val intent = Intent(activity, EditShortInfoActivity::class.java)
    intent.putExtra("title", title)
    intent.putExtra("content", content)
    intent.putExtra("length", length)
    activity.startActivityForResult(intent, requestCode)

    最终在编辑结束后,返回新的昵称:

    val intent = Intent()
    intent.putExtra("content", message)
    setResult(Activity.RESULT_OK, intent)
    finish()

    赶紧运行测试一下,咦咦咦?为什么onActivityResult方法没有回调呢?

    这不是再搞我吗?我十分气愤的吐槽中,首先打开了Fragment的onActivityResult方法:

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
    }

    空方法,说明Fragment内部没有做任何处理,不过问题应该不在这,Fragment被嵌套在Activity中,那么Activity调用了Fragment的可能性肯定是最大的,啥也别说了,看一下FragmentActivity的onActivity方法:

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

    果然看到了我们期待的Fragment对象,那八成问题就在这了,我们先来分析一下代码:

    我们的请求码右移了16位(相当于除了2的16次方,也就是65526),得到了一个索引值,这让我想到了之前我们研究过的哈西算法,然后得到对应的Fragment,如果你Fragment不等于空,就再把请求码再处理一次,然后回调onActivityResult方法。

    我们先来断点看看在我第一次获取系统照片的时候都发生了什么?

    image

    首先我要告诉大家,我自己传的requestCode是101,但是在FragmentActivity的onActivityResult中竟然显示的是327781,那肯定是在调用相册的时候,系统把的请求码处理了,最终走到了Fragment的onActivityResult方法,

    image

    在我的EditUserInfoDetailsFragment得到的是101。

    通过上面的研究,我们得出了结论,当我们在调用系统相册的时候,系统会把我们原来的请求码进行处理,然后再最终把处理过的请求码恢复,我们就可以通过判断我们原本的请求码,知道我们要进行的操作什么。

    现在再来试试第二种情况,因为篇幅的缘故我就不贴图了,直接说出结果(其实是我懒,大家都懂的):

    如果是app内部的startActivityForResult,是不会对请求码进行处理的,也就是说我们传的requestCode是什么,在FragmentActivity中得到也是什么,但是我们的值除以65536,那是肯定是等于0的,所以就什么也不执行了。

    有些朋友说了,那我直接把我的请求码设置到65536以上不就得了?

    我就说为什么你这么机智呢,我就赶紧实验了一下:

    image

    结果很凄凉,只能使用小于16位的requestCode,那就是说不可能大于65536,看来google比我们还机智。

    那有什么办法解决这个问题呢?其实非常的简单,既然系统忽略了我们的请求码,那我们就自己分发请求码就好了:

    /** * 重写此方法,子fragment才能出发回调onActivityResult */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode != RESULT_OK) {
    return;
    }
    FragmentManager fm = getSupportFragmentManager();
    List<Fragment> fragments = fm.getFragments();
    if (fragments != null && fragments.size() > 0) {
    for (Fragment f : fragments) {
    f.onActivityResult(requestCode, resultCode, data);
    }
    }
    }

    我这里把resultCode不是ok的屏蔽了,当时你可以按照你自己的需求删掉就可以了,代码就不用解释了。

    #总结

    为什么android系统对我们的第三方app的请求码处理了呢?

    我猜测可能有两点:

    1、是为了系统安全,就好像7.0以上把文件的uri封装了是一样的道理。

    2、可能是为了区别不同app请求了同一个app,这个值能靠猜了。

    本来我今天是想讨论两个问题,没想到一写就这么长了,所以今天就结束了,如果大家对android为什么这么设计有更深入的了解,可以留言讨论,大家一起学习进步。

    那就这样,祝大家生活愉快。

    相关文章

      网友评论

        本文标题:Fragment的onActivityResult方法为什么有的

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