onActivityResult中的requestCode错误

353

我正在从我的Fragment中使用以下代码启动新的Activity:

startActivityForResult(intent, 1);

并且想要在Fragment的父Activity中处理结果:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Log.d(TAG, "onActivityResult, requestCode: " + requestCode + ", resultCode: " + resultCode);
    if (requestCode == 1) {
        // bla bla bla
    }
}

问题是我在调用startActivityForResult()时,从未收到我刚刚发布的requestCode

我得到了一些类似于0x400010x20001等随机高位设置的内容。文档中没有提到这点。有任何想法吗?


6个回答

918

你正在从你的Fragment调用startActivityForResult()。当你这样做时,requestCode会被拥有该FragmentActivity更改。

如果你想在你的活动中获得正确的resultCode,请尝试以下操作:

更改:

startActivityForResult(intent, 1);

收件人:

getActivity().startActivityForResult(intent, 1);

48
因为它需要决定哪个碎片将结果传递给。所以当碎片调用StartActivityForResult时,requestCode将被Activity更改,这样它就知道如何将结果传递给哪个碎片。如果你真的想在活动中获取结果,只需调用getActivity().startActivityForResult()。 - Changwei Yao
33
提示:如果您在片段中使用 startActivityForResult 并且希望从该片段中的 onActivityResult 获取结果,只需确保在宿主活动中调用 super.onActivityResult(如果您在那里覆盖了此方法)。这是因为活动的 onActivityResult 似乎会调用片段的 onActivityResult。另请注意,请求代码在通过活动的 onActivityResult 传递时会被更改,如 Dimanoid 在下面他的答案中所解释的那样。 您可能不需要知道这一点,但您永远不知道…… - Ferran Maylinch
41
"requestCode是由拥有Fragment的Activity更改的" - 安卓的设计真是赞啊... - Bitcoin Cash - ADA enthusiast
21
这是非常重要的信息,但在文档中却找不到清晰的说明。真是太爱安卓设计了,它让你的生活变成了地狱。 - Driss Bounouar
1
在您的FragementActivity中,您也可以在调用fragment.onActivityResult(arg1,arg2,arg3)之前调用super.onActivityResult(arg1,arg2,arg3) - wqycsu
显示剩余5条评论

45

请求代码并没有错误。当使用v4 support库的片段时,片段索引被编码在请求代码的高16位中,而您的请求代码位于低16位中。稍后将使用片段索引来查找正确的片段以传递结果。

因此,对于从片段对象启动的活动,请像以下方式处理onActivityResult requestCode:

originalRequestCode = changedRequestCode - (indexOfFragment << 16)
      6             =      196614        -       (3 << 16)

1
很棒的信息,解释了这个问题的确切原因。 - Muzikant
快速问题:indexOfFragment是什么? - Louis Tsai
indexOfFragment是通过调用getSupportFragmentManager().getFragments()方法产生的索引。 - HerberthObregon
士气:不要混淆在活动/片段中使用startActivityForResult()和onActivityResult()。当从活动开始时,在活动中处理结果。当从片段开始时,在片段中处理结果。 - Yohanim

39

更简单的方法:

Java: int unmaskedRequestCode = requestCode & 0x0000ffff

Kotlin: val unmaskedRequestCode = requestCode and 0x0000ffff

检查低16位,只需将其与高16位进行逻辑与运算即可清除掩码。

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    final int unmaskedRequestCode = requestCode & 0x0000ffff

    if(unmaskedRequestCode == ORIGINAL_REQUEST_CODE){
      //Do stuff

    }
}

1
你能告诉我为什么它没有给出原始请求代码的原因吗? - K.Sopheak
4
由于拥有该片段的活动更改了requestCode,因此请参阅Ashlesha Sharma的答案。 - Jaime Agudo
谢谢,这就是我在寻找的答案。不过我不明白为什么Android不应该返回原始的请求代码。 - tonisives
今天这对我非常有帮助,而且很好地解释了问题。谢谢! - Billy Lazzaro

6
如果您提供常量,请将其公开,然后在startActivityResult中使用。
例如:
public static final int REQUEST_CODE =1;
getActivity().startActivityForresult(intent, REQUEST_CODE);

2
你也可以在Activity中定义
super.onActivityResult(requestCode, resultCode, data)
(如果你重写onActivityResult
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {

        ...

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

在你的Fragment中调用 startActivityForResult(intent, requestCode)

0

在片段中

  getActivity().startActivityForResult(builder.build(getActivity()), PLACE_PICKER_REQUEST);

在主活动中:

if (requestCode == PLACE_PICKER_REQUEST) {
            if (resultCode == RESULT_OK) {    
     //what ever you want to do
            }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接