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

Что такое Target Fragment?

1.0 Junior🔥 91 комментариев
#Android компоненты

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

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

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

Target Fragment в Android

Target Fragment — это паттерн для передачи результатов между Fragment'ами без использования Activity в качестве посредника. Это способ, который был популярен до появления Navigation Component.

Проблема: Как передать результат между Fragments?

Без Target Fragment нужна Activity как посредник:

// Fragment 1
class UserListFragment : Fragment() {
    fun onUserSelected(user: User) {
        (activity as MainActivity).showUserDetail(user)
    }
}

// Activity
class MainActivity : AppCompatActivity() {
    fun showUserDetail(user: User) {
        // Activity связывает Fragments
    }
}

Проблемы:

  • Fragment зависит от конкретной Activity
  • Сложно переиспользовать Fragment
  • Нарушает Single Responsibility

Решение: Target Fragment

Target Fragment — фрагмент, установленный как получатель результата:

// Отправитель результата
class UserSelectionDialog : DialogFragment() {
    fun showDialog(targetFragment: Fragment) {
        setTargetFragment(targetFragment, REQUEST_CODE)
        show(targetFragment.parentFragmentManager, "dialog")
    }
    
    private fun onUserSelected(user: User) {
        targetFragment?.onActivityResult(
            REQUEST_CODE,
            Activity.RESULT_OK,
            Intent().apply {
                putExtra("user", user)
            }
        )
        dismiss()
    }
    
    companion object {
        const val REQUEST_CODE = 100
    }
}

// Получатель результата
class UserListFragment : Fragment() {
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        
        if (requestCode == UserSelectionDialog.REQUEST_CODE && resultCode == Activity.RESULT_OK) {
            val user = data?.getSerializableExtra("user") as? User
            user?.let { updateUI(it) }
        }
    }
    
    fun showSelectionDialog() {
        UserSelectionDialog().showDialog(this)
    }
}

Современный подход: Fragment Result API

Google рекомендует использовать Fragment Result API:

// Отправитель результата
class UserSelectionDialog : DialogFragment() {
    private fun onUserSelected(user: User) {
        parentFragmentManager.setFragmentResult(
            "user_selection",
            bundleOf("user" to user)
        )
        dismiss()
    }
}

// Получатель результата
class UserListFragment : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        parentFragmentManager.setFragmentResultListener(
            "user_selection",
            viewLifecycleOwner
        ) { key, bundle ->
            val user = bundle.getParcelable<User>("user")
            updateUI(user)
        }
    }
}

Практические примеры

1. Диалог выбора даты

class DatePickerDialog : DialogFragment() {
    fun show(targetFragment: Fragment, requestCode: Int) {
        setTargetFragment(targetFragment, requestCode)
        show(targetFragment.parentFragmentManager, "date_picker")
    }
    
    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        return AlertDialog.Builder(requireContext())
            .setTitle("Выбери дату")
            .setPositiveButton("OK") { _, _ ->
                targetFragment?.onActivityResult(
                    targetRequestCode,
                    Activity.RESULT_OK,
                    Intent().apply {
                        putExtra("date", System.currentTimeMillis())
                    }
                )
                dismiss()
            }
            .setNegativeButton("Отмена") { _, _ -> dismiss() }
            .create()
    }
}

2. Диалог подтверждения

class ConfirmDialog : DialogFragment() {
    fun show(
        targetFragment: Fragment,
        message: String,
        requestCode: Int
    ) {
        setTargetFragment(targetFragment, requestCode)
        show(targetFragment.parentFragmentManager, "confirm")
    }
    
    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        return AlertDialog.Builder(requireContext())
            .setMessage("Удалить?")
            .setPositiveButton("Да") { _, _ ->
                targetFragment?.onActivityResult(
                    targetRequestCode,
                    Activity.RESULT_OK,
                    null
                )
                dismiss()
            }
            .setNegativeButton("Нет") { _, _ -> dismiss() }
            .create()
    }
}

Жизненный цикл

// 1. Fragment A устанавливает Target Fragment B
setTargetFragment(fragmentB, REQUEST_CODE)

// 2. Fragment B выполняет действие
// 3. Fragment B отправляет результат Fragment A
fragmentA?.onActivityResult(REQUEST_CODE, RESULT_OK, intent)

// 4. Fragment A обрабатывает результат
override fun onActivityResult(requestCode, resultCode, data) {
    // Обработка
}

Миграция на Fragment Result API

// Старый код
setTargetFragment(this, REQUEST_CODE)
targetFragment?.onActivityResult(REQUEST_CODE, Activity.RESULT_OK, intent)

// Новый код
parentFragmentManager.setFragmentResult(
    "key",
    bundleOf("result" to value)
)

parentFragmentManager.setFragmentResultListener(
    "key",
    viewLifecycleOwner
) { _, bundle ->
    val result = bundle.get("result")
}

Сравнение подходов

ПодходПлюсыМинусы
Target FragmentПростойDeprecated
Прямая связьLifecycle проблемы
Fragment Result APIСовременныйТребует parentFragmentManager
Type-safe
Navigation ComponentЛучший UXСложнее
SafeArgs

Best Practices

  1. Используй Fragment Result API для новых проектов
  2. Всегда проверяй наличие targetFragment
  3. Используй константы для REQUEST_CODE
  4. Обрабатывай все коды результатов
  5. Мигрируй старый код на современный API

Вывод: Target Fragment — deprecated паттерн. Для новых проектов используй Fragment Result API, который более безопасен и удобен.