Комментарии (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
- Используй Fragment Result API для новых проектов
- Всегда проверяй наличие targetFragment
- Используй константы для REQUEST_CODE
- Обрабатывай все коды результатов
- Мигрируй старый код на современный API
Вывод: Target Fragment — deprecated паттерн. Для новых проектов используй Fragment Result API, который более безопасен и удобен.