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

Что используешь если надо передать объект с фрагмента на фрагмент

1.0 Junior🔥 211 комментариев
#Android компоненты#Жизненный цикл и навигация

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

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

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

Отличный вопрос! Это одна из самых частых и важных тем в Android-разработке. Для передачи данных между фрагментами существует несколько подходов, и выбор лучшего зависит от контекста: объема данных, связи между фрагментами, требований к жизненному циклу и архитектуры приложения.

Я всегда рекомендую использовать ViewModel в сочетании с SavedStateHandle или интерфейсы обратного вызова (callback interfaces) через общую Activity, так как они являются наиболее корректными с точки зрения архитектурных рекомендаций Google (Android Jetpack) и учитывают жизненный цикл.

Вот основные подходы, от менее к более предпочтительным:

1. Через общую Activity (ViewModel или Интерфейсы)

Это самый чистый и рекомендуемый способ, обеспечивающий слабую связность и корректную работу с жизненным циклом.

Использование Shared ViewModel

ViewModel, размещенная в scope родительской Activity или NavGraph, становится единым источником правды для всех фрагментов. Это идеально для данных, которые должны переживать уничтожение/создание фрагментов.

// 1. Создаем Shared ViewModel. Важно использовать owner как activity
class SharedViewModel : ViewModel() {
    private val _selectedItem = MutableLiveData<DataObject>()
    val selectedItem: LiveData<DataObject> = _selectedItem

    fun selectItem(item: DataObject) {
        _selectedItem.value = item
    }
}

// 2. Во Fragment-отправителе
class SenderFragment : Fragment() {
    private val sharedViewModel: SharedViewModel by activityViewModels()

    private fun sendData() {
        val myData = DataObject(...)
        sharedViewModel.selectItem(myData)
    }
}

// 3. Во Fragment-получателе
class ReceiverFragment : Fragment() {
    private val sharedViewModel: SharedViewModel by activityViewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        sharedViewModel.selectedItem.observe(viewLifecycleOwner) { item ->
            // Обновляем UI полученными данными
            updateUI(item)
        }
    }
}

Для навигации с Navigation Component часто используют ViewModel с SavedStateHandle, чтобы данные пережили процесс death и recreation:

class SharedViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() {
    var importantData: DataObject?
        get() = savedStateHandle.get<DataObject>("key")
        set(value) = savedStateHandle.set("key", value)
}

Использование Интерфейса обратного вызова

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

// 1. Определяем интерфейс в Fragment-отправителе
class SenderFragment : Fragment() {
    interface OnDataPassListener {
        fun onDataPassed(data: DataObject)
    }
    private var listener: OnDataPassListener? = null

    // 2. Activity реализует этот интерфейс и перенаправляет данные
    override fun onAttach(context: Context) {
        super.onAttach(context)
        listener = context as? OnDataPassListener
    }

    private fun passData() {
        listener?.onDataPassed(DataObject(...))
    }
}

// 3. В Activity или целевом Fragmentе
class HostActivity : AppCompatActivity(), SenderFragment.OnDataPassListener {
    override fun onDataPassed(data: DataObject) {
        // Передаем данные в целевой фрагмент, например, через его метод
        val receiverFragment = supportFragmentManager.findFragmentById(R.id.receiver) as? ReceiverFragment
        receiverFragment?.receiveData(data)
    }
}

2. Использование аргументов (Bundle) - ТОЛЬКО при навигации

Это стандартный способ передать данные при создании или переходе к фрагменту. Bundle следует использовать только для простых, сериализуемых данных, которые не изменяются после установки.

// Создание фрагмента с аргументами
val receiverFragment = ReceiverFragment().apply {
    arguments = Bundle().apply {
        putParcelable("data_key", myParcelableObject)
        // или для большого объекта putSerializable("key", mySerializableObject)
    }
}

// В Fragment-получателе
class ReceiverFragment : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val receivedData = arguments?.getParcelable<DataObject>("data_key")
        // Используем данные
    }
}

Важно: Для этого объект должен реализовывать интерфейс Parcelable (предпочтительнее, быстрее) или Serializable.

3. Прямое взаимодействие (НЕ РЕКОМЕНДУЕТСЯ)

Находить фрагмент по тегу или ID и вызывать его методы напрямую — это антипаттерн, который создает жесткую связь и приводит к проблемам с жизненным циклом.

// ПЛОХОЙ ПРИМЕР - Избегайте этого!
val receiverFragment = parentFragmentManager.findFragmentByTag("receiver") as? ReceiverFragment
receiverFragment?.receiveDataDirectly(data)

4. Использование EventBus или RxJava

Библиотеки вроде EventBus или реактивные потоки RxJava/ Kotlin Flow могут использоваться для глобальной коммуникации, но часто являются избыточными для простой передачи между фрагментами и могут скрывать связи в коде.

Краткие рекомендации по выбору:

  • ViewModel (activityViewModels): Используйте всегда, когда фрагменты находятся в одной Activity и работают с общими, изменяемыми данными. Это лучшая практика.
  • Аргументы (Bundle): Используйте только для начальной передачи данных при создании фрагмента (например, ID для загрузки деталей). Данные становятся "замороженными".
  • Интерфейсы через Activity: Хороши, когда нужно триггерить конкретное действие в другом фрагменте (например, "обнови список").
  • Прямые вызовы и глобальные шины: Избегайте для этой задачи, они нарушают инкапсуляцию и усложняют поддержку.

Итог: Для современной разработки на Kotlin с Jetpack ваш основной инструмент — Shared ViewModel, управляющая состоянием экрана. Для передачи начальных параметров при навигации используйте аргументы (Bundle), упаковав данные в Parcelable объект. Эта комбинация покрывает 99% случаев, обеспечивая чистую архитектуру, обработку конфигурационных изменений и предсказуемое состояние.

Что используешь если надо передать объект с фрагмента на фрагмент | PrepBro