← Назад к вопросам

Что такое Fragment Result API?

2.0 Middle🔥 202 комментариев
#Жизненный цикл и навигация

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое Fragment Result API?

Fragment Result API — это современный механизм передачи данных между фрагментами в Android, представленный в AndroidX Fragment версии 1.3.0. Он призван заменить устаревший подход с использованием прямого вызова методов фрагментов (например, setTargetFragment() и onActivityResult()), который создавал тесную связь между компонентами и усложнял жизненный цикл.

Основная проблема, которую решает API

Ранее для получения результата от одного фрагмента (например, диалога выбора даты) в другой фрагмент (родительский) нужно было:

  1. Устанавливать целевой фрагмент через setTargetFragment().
  2. Передавать данные через интенты или Bundle.
  3. Обрабатывать результат в onActivityResult() родительского фрагмента.

Этот подход был подвержен ошибкам, особенно при изменении состояния фрагментов (поворот экрана, восстановление из бэкстэка), и создавал жесткие зависимости.

Ключевые компоненты API

API основан на двух основных понятиях:

  1. setFragmentResult() — метод для отправки результата. Он принимает:
    *   `requestKey` — уникальный ключ для идентификации запроса (строка).
    *   `result` — данные в виде `Bundle`.
  1. setFragmentResultListener() — метод для подписки на результат. Он принимает:
    *   `requestKey` — тот же ключ, что и при отправке.
    *   `LifecycleOwner` (обычно сам фрагмент).
    *   `FragmentResultListener` — лямбда-коллбек, который будет вызван при получении результата.

Как это работает

Результаты управляются FragmentManager, который выступает в роли централизованного хранилища. Данные сохраняются даже при уничтожении и повторном создании фрагментов, что решает проблему конфигурационных изменений.

Пример использования

Предположим, у нас есть ParentFragment, который открывает DatePickerDialogFragment и ожидает от него выбранную дату.

1. Родительский фрагмент (слушатель):

class ParentFragment : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // Устанавливаем слушатель с уникальным ключом "REQUEST_KEY_DATE"
        parentFragmentManager.setFragmentResultListener(
            "REQUEST_KEY_DATE", // Ключ запроса
            viewLifecycleOwner,  // LifecycleOwner
            { requestKey, result ->
                // Коллбек сработает при получении данных
                if (requestKey == "REQUEST_KEY_DATE") {
                    val selectedDate = result.getLong("SELECTED_DATE_MILLIS")
                    // Обрабатываем полученную дату
                    updateUIWithDate(selectedDate)
                }
            }
        )

        buttonPickDate.setOnClickListener {
            // Запускаем фрагмент-диалог
            DatePickerDialogFragment().show(parentFragmentManager, "DatePicker")
        }
    }

    private fun updateUIWithDate(dateMillis: Long) {
        // Обновляем интерфейс
    }
}

2. Фрагмент-диалог (отправитель результата):

class DatePickerDialogFragment : DialogFragment() {
    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        // ... создание DatePickerDialog

        datePickerDialog.setButton(DialogInterface.BUTTON_POSITIVE, "OK") { _, _ ->
            val selectedDateInMillis = // ... получаем выбранную дату

            // Отправляем результат обратно
            val result = bundleOf("SELECTED_DATE_MILLIS" to selectedDateInMillis)
            parentFragmentManager.setFragmentResult("REQUEST_KEY_DATE", result)

            dismiss()
        }
        return datePickerDialog
    }
}

Преимущества перед старым подходом

  • Отсутствие прямой зависимости: Фрагменты не знают друг о друге. Они общаются только через FragmentManager по согласованному ключу.
  • Безопасность жизненного цикла: Слушатель автоматически удаляется при уничтожении LifecycleOwner (например, viewLifecycleOwner), что предотвращает утечки памяти и вызовы в неактивном состоянии.
  • Сохранение состояния: Результаты сохраняются при смене конфигурации. Если получатель был уничтожен и еще не восстановлен, он получит результат, как только его Lifecycle станет активным.
  • Упрощение кода: Не нужно реализовывать onActivityResult() или отслеживать requestCode.
  • Возможность многоадресной рассылки: Несколько слушателей могут подписаться на один requestKey.

Важные ограничения и нюансы

  1. FragmentManager как область видимости: Данные передаются в пределах одного FragmentManager. Для передачи между фрагментами, находящимися в разных FragmentManager (например, вложенных), нужно использовать childFragmentManager.
  2. Единоразовость: Результат может быть получен слушателем только один раз. После обработки он очищается. Если нужно передать данные несколько раз, нужно каждый раз вызывать setFragmentResult().
  3. Ключи должны быть уникальными: Желательно использовать осмысленные, уникальные строковые константы или механизмы вроде View.generateViewId() для генерации ключей в рантайме, чтобы избежать конфликтов.

Заключение

Fragment Result API — это декларативный и жизненный цикл-безопасный способ коммуникации между фрагментами, соответствующий современным архитектурным рекомендациям Google (например, Model-View-ViewModel). Он минимизирует связанность компонентов, устраняет целый класс ошибок, связанных с жизненным циклом, и является предпочтительной практикой для новых проектов вместо устаревших методов setTargetFragment() и onActivityResult().

Что такое Fragment Result API? | PrepBro