Очистить тему про onActivityResult management с действиями и фрагментами - PullRequest
2 голосов
/ 05 июня 2019

Я пишу этот вопрос StackOverflow, потому что я не прочитал четкое решение вопроса о функционировании Android onActivityResult, когда задействованы фрагменты и действия. То, что я хотел бы иметь (даже при том, что я почти уверен, что у меня не будет большого участия), было бы иметь элементы здесь, чтобы понять, как onActivityResult в каждом случае, поскольку некоторые из них кажутся довольно случайными.

Из того, что я видел в вопросах о SO, есть классический случай (startActivityForResult и onActivityResult для одного и того же упражнения) и 3 запутанных / не работающих случая:

  • Вызов startActivityForResult из фрагмента и использование onActivityResult в родительской активности

  • Вызов startActivityForResult из действия и использование onActivityResult на фрагменте, принадлежащем деятельности

  • Вызов startActivityForResult из фрагмента и использование onActivityResult для фрагмента

Мой первый вопрос: готов ли Android API для этих случаев использования? И тогда главный вопрос: как это работает? Потому что даже со ссылкой на Google единственным описанным вариантом использования, который я видел, был классический случай. Другие случаи кажутся мне неясными из того, что я читал по другим вопросам об этом.

Ответы [ 2 ]

2 голосов
/ 05 июня 2019

Надеюсь, я смогу вам помочь.Несмотря на отсутствие документации, вы можете просмотреть исходный код и проверить, как он работает.То, что я мог наблюдать и могу ошибаться, это:

Начиная с упражнения

Activity.startActivityForResult(requestCode) --- > Activity.onActivityResult(requestCode)

Начиная с фрагмента

Fragment.startActivityForResult(requestCode) -> Activity.startActivityForResult(maskedRequestCode) -> |
                                                                                                      |
                                                                                                      |
  Fragment.startActivityForResult(requestCode) <--  Activity.onActivityResult(maskedRequestCode)  < - |

Как вы можете видеть, когда вы вызываете Fragment.startActivityForResult, фрагмент будет вызывать аналогичный метод с хоста Activity.Однако хост Activity замаскирует этот requestCode, чтобы узнать, какой фрагмент вызвал это действие.Таким образом, во время onActivityResult, Activity будет снимать маску с этого значения, чтобы доставить результат в соответствующий фрагмент (поскольку действие может содержать несколько фрагментов и т. Д.).

Итак, исходя из этого,Вы должны начать действие и обработать его результат на том же элементе.В противном случае вы не сможете правильно определить requestCode.Потому что если Fragment запустил действие, то хостинг будет иметь доступ только к маскированному значению (без копирования кода для снятия маски с этого значения вы не можете определить requestCode для принятия надлежащих действий).

Помните, что вы можете общаться со своей деятельностью из фрагмента:

class MainActivity {
    public void startActivityX() {
        startActivityForResult(ACTIVITY_X_REQUEST_CODE);
    }
}

class MainFragment {
    public void startActivityX() {
        ((MainActivity)getActivity()).startActivityX();
    }
}

Обратное также допустимо. Вы можете получить экземпляр Fragment, привести к MainFragment и вызвать методы, которые вынужно.

Как правило, вы должны:

  • Если старт / результат обрабатывается Activity, запуск и обработка с помощью Activity

  • Если запуск / перезапуск будет обрабатываться Fragment, запустите запуск и обработайте с помощью Fragment

  • Если запуск / результат распределяется между Fragment и Activity, запустите и обработайте его с помощью Activity.Затем действие вызывает методы на Fragment.В вашем Fragment вы можете получить Activity через getActivity().Кроме того, на Activity вы можете получить ссылку на Fragment через getFragmentByTag() Таким образом, можно вызывать методы элемента из другого элемента и наоборот.

ЗДЕСЬ Я также рассказал, как маскируется requestCode и т. Д. Это может помочь вам.

1 голос
/ 05 июня 2019

Ответ W0rmH0le хорош, и я согласен с тем, что он написал. Тем не менее, я хотел пролить свет на то, почему люди думают, что Fragment.startActivityForResult() сломан.

onActivityResult() не выдает исключение, если вам не удается позвонить super.onActivityResult(). Тем не менее, вы должны вызывать super , если вы переопределяете этот метод в своей деятельности и хотите иметь возможность обрабатывать результаты в ваших фрагментах.

super.onActivityResult() - это механизм, который разоблачает код запроса и отправляет результат во фрагмент. Итак, если ваша активность имеет код, который выглядит следующим образом:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == foo) {
        // do something
    }
}

Это сломает ваши фрагменты . Добавить super вызов:

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

    if (requestCode == foo) {
        // do something
    }
}

Теперь замаскированный код запроса будет обработан правильно, и результат будет отправлен в ваш фрагмент, как и ожидалось.

...