Android HTTP обратный вызов и обработка фрагментов - PullRequest
0 голосов
/ 02 апреля 2020

У меня есть следующий код (его скелет):

PostRequester(..., Fragment caller, final PostRequesterResponse callback  ) {
        StringRequest stringRequest = new StringRequest(Request.Method.POST, baseUrl,
                response -> {
                    if (callback != null && caller != null) {
                        callback.onResponse(response);
                    }
                })...

Пример вызова выше, из фрагмента:

...(this, result -> {
            try {
                if (result.contains("error")) {
                    throw new Exception(new JSONObject(result).getString("error"));
                }
                JSONObject jo = new JSONObject(result).getJSONObject("result");
                tvIncome.setText(getString(R.string.income));
            } catch (Exception e) {
                ...showPopup(getString(...));
            }

Я проверяю этот обратный вызов и Вызывающая сторона не пуста, но я получаю следующее:

Fatal Exception: java.lang.IllegalStateException: Fragment x2{8dc73ab (83fe8dc9-f7d2-4324-abf2-c4aae15c37ef)} not attached to a context.

Сначала происходит сбой getString(), а затем в исключении. Возможно, вызывающая сторона не нулевая, но она отсоединена. Я могу добавить условие caller.isDetached(), но пользователь может "go back" и отсоединить фрагмент в любое время. Проверка isDetached после каждой строки кода не очень хорошая идея.

Что можно сделать в этой ситуации? Спасибо

Ответы [ 2 ]

0 голосов
/ 03 апреля 2020

Вы можете добавить caller.isDetached() к условию обратного вызова. Как вы упомянули, but the user might "go back" and detach the fragment at any time. в этом случае вы бы не хотели, чтобы фрагмент все равно получал обратный вызов. Если вы хотите обработать ответ независимо от фрагмента, вы должны вызывать его не из фрагмента, а из другого места, более устойчивого. В этом случае я бы предложил не включать фрагмент в logi c запроса, а только обратный вызов, на который может зарегистрироваться любой вызывающий объект.

для вашего последующего вопроса:

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

1. объявить интерфейс с именем INetworkListener с методом onResponse(Response response)

2. FragmentX реализует INetworkListener

3. В FragmentX переопределить onResponse (ответ ответа) и обработайте ответ там

4. Когда вы делаете сетевой вызов вместо фрагмента и обратного вызова в качестве аргументов, используйте аргумент callback типа INetworkListener (который является тем, кто реализует этот интерфейс, в нашем случае, фрагмент. Поэтому, если вызывается из фрагмента, аргумент будет быть this.

5. внутри вашей функции вызова, когда ответ готов, вызовите callback.onResponse(response), как вы делаете сейчас, и фрагмент получит его в методе onResponse (), который его переопределяет.

Чем оно отличается от того, что есть у вас сейчас? Ну, технически это не так.
По сути, передача фрагмента в качестве аргумента может быть источником утечек памяти и не очень хорошая практика. .

Это важно при выполнении вызова. Например, если вы вызываете его во фрагменте onCreate, ответ может вернуться до того, как фрагмент будет прикреплен.
Проблема с вашим кодом состоит в том, что он не с учетом состояния фрагмента перед доступом к его интерфейсу.
Если вы хотите обновить фрагмент после его возобновления, вы можете использовать команду ca Вернемся к проверке типа if (!fragment.isAdded) return перед обновлением пользовательского интерфейса фрагмента в ответ, если фрагмент был отсоединен.
Но если вы хотите загрузить фрагмент с данными, я бы порекомендовал подготовить сетевые данные. заранее инициализировать фрагмент с данными и НЕ использовать обратный вызов для фрагмента для этой цели.

0 голосов
/ 03 апреля 2020

Как я вижу, вы должны вызывать getActivity (). GetString () просто так:

tvIncome.setText (getActivity (). GetString (R.string.income))

Но также необходимо проверить, что getActivity () не равно нулю !!!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...