【问题标题】:Fragment's onActivityResult not called after orientation change方向更改后未调用片段的 onActivityResult
【发布时间】:2014-02-13 17:20:54
【问题描述】:

请注意,此问题与以下问题不重复:

另外,之前有人问过另一个similar question,但没有提到方向变化(并且未解决)。

如果我不切换方向,Fragment 中的 onActivityResult 方法会被调用。但是,如果我按照这些步骤操作,它不会被调用:

  1. 在 FragmentActivity 中加载片段。
  2. 来自片段:startActivityForResult(new Intent(MediaStore.ACTION_IMAGE_CAPTURE), Constants.REQ_CODE_IMAGE_CAPTURE);
  3. 等待相机加载。
  4. 切换方向。
  5. 拍照并点击复选标记。

onActivityResult 仍然在父 FragmentActivity 中被调用。但是,由于这个警告,我得到:

W/FragmentActivity(4418): Activity result no fragment exists for index: 0x22d73

...我的猜测是父级由于方向变化而被破坏,并且在重新创建后,首先找不到调用startActivityForResultFragment

这是一个框架错误吗?如何解决这个问题?

编辑:应大众需求添加了更多代码。

FragmentActivity.java:

...

fragment = new ExampleFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace (R.id.mainContentView, fragment);
if (clearBackStack) {
    // clear the back stack
    while (getSupportFragmentManager().popBackStackImmediate ());
    // add the current transaction to the back stack
    transaction.addToBackStack (null);
}
else {
    transaction.addToBackStack(null);
}
transaction.commit();

...

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

ExampleFragment.java:

Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(takePicture, Constants.REQ_CODE_IMAGE_CAPTURE);

...

@Override
public void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
    switch (requestCode) {
    case Constants.REQ_CODE_IMAGE_CAPTURE:
        // handle added image
    }
}

【问题讨论】:

  • @shomeser,你的帖子是在搜索东西时出现的,但我没有嵌套片段,所以我认为它不相关。
  • 您的片段索引太大:0x22d73,看起来发生了一些奇怪的事情。这个问题能否稳定重现?你能展示你的代码吗?
  • @shomeser,我的代码并没有什么特别之处,但请参阅编辑。如果您按照提供的步骤操作,问题总是可以重现的。
  • 您是否尝试在 beginTransaction() 之前移动 popBackStackImmediate() 的调用??

标签: android android-fragments orientation-changes


【解决方案1】:

通过将所有onActivityResult 逻辑从Fragment 移动到Activity 来解决它。

请注意,但是,传递给 FragmentreqCode 与传递给父 ActivityreqCode 不同(@ 987654329@ 是我认为的系统设置的)。这意味着我还必须将原始的startActivityForResult 调用从Fragment 移动到Activity,然后创建一个方法来在需要时从Fragment 调用它。

如果有人找到更优雅的方式,我会很高兴听到。

【讨论】:

  • 参见方法 FragmentActivity.startActivityFromFragment(),它修改了原始请求代码以存储 Fragment 的索引:goo.gl/yuaPWW 这就是为什么你得到不同的值。很遗憾,但目前我无法重现此问题。
  • 该修复对我有用。该问题仅出现在某些设备上(Galaxy S5 很好,但我在 Sony XPeria 上遇到了错误)
  • 在我的情况下,onActivityResult 已经在我的 Activity 类上。但我仍然注意到同样的行为。
【解决方案2】:

我有一个解决方案 它目前正在我的项目中工作。 按照步骤。

--> 创建接口名称 OnActivityResultListener(或您希望的名称)。

公共接口 OnActivityResultListener {

public boolean onActivityResultTest(int request_code, int response_code,
        Intent data);

}

--> 在你的 FragmentActivity 中引用 intercace 就像

public OnActivityResultListener activityResultListener;

--> 现在覆盖 FragmentActivity 中的 OnActivityResult。如下所示。

@Override
public void onActivityResult(int arg0, int arg1, Intent arg2) {
    AppLog.Log(TAG, "onActivityResult");
    try {
        if (activityResultListener != null) {
            activityResultListener.onActivityResultTest(arg0,arg1,arg2);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    super.onActivityResult(arg0, arg1, arg2);
    }

--> 现在在 Fragment 中实现接口并覆盖所需的方法。

@Override
public boolean onActivityResultTest(int requestCode, int resultCode,
        Intent data) {
    AppLog.Log(TAG, "onActivityResultTest");
    if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) {
        isHavePhoto = true;
        bitmap = (Bitmap) data.getExtras().get("data");
        userEditPhoto.setImageBitmap(bitmap);
    }
}

--> 最后一步是在 Fragment 类的 OnAttach 方法中,将您的 Fragment 注册到 Activity 中以获得 Activity 结果。喜欢

@Override
    public void onAttach(Activity activity) {
        this.activity = (YOUR_FRAGMENT_ACTIVITY) activity;
            this.activity.activityResultListener = this;
        super.onAttach(activity);
    }

-->现在测试,别忘了删除它

@Override
public void onDestroyView() {
    activity.activityResultListener = null;
    super.onDestroyView();
}

->这是一个漫长的过程,但它在任何方向上都能 100% 工作。

【讨论】:

  • 不适用于 Android 4.4、Nexus 5、19.0.1 版本的支持库。 Fragment 在Activity 的onActivityResult 被调用后被附加,所以在它被调用时,监听器为空。
  • 对不起,但它适用于 4.4,我已经在 Nexus 4 和 5 中进行了测试,它也可以正常工作。你需要告诉我我认为你的 onAttach 方法有问题。再次检查所有步骤。
  • 嗯,可能是这样。但是,在我目前的情况下,它对我不起作用。
  • 工作正常,只需从活动中调用startActivityForResult (activity?.startActivityForResult)
猜你喜欢
  • 2011-09-03
  • 2019-12-05
相关资源
最近更新 更多