OnActivityResult фрагмента не вызывается после изменения ориентации

Обратите внимание, что этот вопрос не является дубликатом следующего:

Кроме того, раньше был задан еще один аналогичный вопрос , но это не говорит об изменении ориентации (и это не решено).

Мой метод onActivityResult в Fragment вызывается, если я не переключаю ориентацию. Однако, если я выполню следующие шаги, он не будет вызван:

  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

... я предполагаю, что родительский элемент был уничтожен из-за изменения ориентации, и после повторного создания не может найти Fragment, который вызвал startActivityForResult.

Это ошибка фреймворка? Как это можно обойти?

РЕДАКТИРОВАТЬ: добавлен дополнительный код по многочисленным просьбам.

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
    }
}

person Shade    schedule 23.01.2014    source источник
comment
Проблема в библиотеке поддержки. Проверьте это сообщение: shomeser.blogspot.com/2014/01/ вложенные-фрагменты-для-результата.html   -  person Oleksii K.    schedule 23.01.2014
comment
@shomeser, ваш пост появился при поиске чего-то, но у меня нет вложенных фрагментов, поэтому я не думаю, что это связано.   -  person Shade    schedule 23.01.2014
comment
индекс вашего фрагмента слишком велик: 0x22d73, похоже, что-то странное произошло. стабильна ли эта проблема для воспроизведения? не могли бы вы показать свой код?   -  person Oleksii K.    schedule 23.01.2014
comment
@shomeser, в моем коде нет ничего особенного, но посмотрите правку. Проблема всегда воспроизводима, если вы выполните указанные действия.   -  person Shade    schedule 23.01.2014
comment
Вы пытались переместить вызов popBackStackImmediate () до beginTransaction () ??   -  person Oleksii K.    schedule 24.01.2014


Ответы (2)


Решил эту проблему, переместив всю логику onActivityResult с Fragment на Activity.

Обратите внимание, однако, что reqCode, который передается в Fragment, отличается от reqCode, который передается родительскому Activity (я думаю, что для Activity устанавливается система). Это означало, что мне также пришлось переместить исходный вызов startActivityForResult из Fragment в Activity, а затем создать метод для его вызова из Fragment, когда это необходимо.

Если кто-нибудь найдет способ более элегантный, я буду рад услышать об этом.

person Shade    schedule 23.01.2014
comment
См. Метод FragmentActivity.startActivityFromFragment (), он изменяет исходный код запроса для хранения индекса фрагмента: goo.gl/yuaPWW Вот почему у вас другая ценность. К сожалению, в настоящее время я не могу воспроизвести эту проблему. - person Oleksii K.; 24.01.2014
comment
Это исправление сработало для меня. Проблема возникла только на некоторых устройствах (Galaxy S5 был в порядке, но у меня была ошибка на Sony XPeria) - person Arnaud; 03.10.2014
comment
В моей ситуации onActivityResult уже был в моем классе Activity. Но я все еще замечаю такое же поведение. - person Neon Warge; 02.03.2015

У меня есть одно решение, которое в настоящее время работает в моем проекте. следуйте шагу.

-> Создайте имя интерфейса OnActivityResultListener (или имя, как хотите).

открытый интерфейс OnActivityResultListener {

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

}

-> Сделайте ссылку на интерфейс в вашем FragmentActivity, например

public OnActivityResultListener activityResultListener;

-> теперь переопределить OnActivityResult в FragmentActivity. как показано ниже.

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

-> теперь реализуйте интерфейс в вашем фрагменте и переопределите требуемый метод.

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

-> и последний шаг находится внутри метода OnAttach класса Fragment - зарегистрируйте ваш фрагмент в действии для результата 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% в любой ориентации.

person Imtiyaz Khalani    schedule 23.01.2014
comment
Не работает на Android 4.4, Nexus 5, ревизия 19.0.1 библиотеки поддержки. Фрагмент прикрепляется после вызова onActivityResult Activity, поэтому во время его вызова слушатель имеет значение NULL. - person Shade; 23.01.2014
comment
извините, но он работает с 4.4, я тестировал в Nexus 4 и 5, он тоже работает. вам нужно сказать мне, что я думаю, что у вас проблема с методом onAttach. проверьте все шаги еще раз. - person Imtiyaz Khalani; 24.01.2014
comment
Что ж, может быть. Однако в моей нынешней ситуации у меня это не работает. - person Shade; 24.01.2014
comment
Работает нормально, просто нужно вызвать startActivityForResult из активности (activity?.startActivityForResult) - person Francis; 17.08.2018