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

Что такое Context в Jetpack Compose?

2.3 Middle🔥 221 комментариев
#Архитектура и паттерны

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

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

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

Что такое Context в Jetpack Compose?

В Jetpack Compose понятие Context отличается от традиционного Context в Android на основе Views (Activity, Application Context). В Compose Context — это, прежде всего, CompositionLocal или набор параметров, которые передаются через дерево композиции и предоставляют компонентам доступ к важным данным и ресурсам.

Основные формы Context в Compose

1. Ambient (устаревший) / CompositionLocal

Это основной механизм передачи "контекстных" данных. CompositionLocal позволяет предоставлять значения (например, LocalContext, LocalConfiguration) которые автоматически доступны всем composable-функциям внутри определенной части дерева.

@Composable
fun MyScreen() {
    // Получаем традиционный Android Context (обычно Activity)
    val androidContext = LocalContext.current
    
    // Использование Context для получения ресурсов
    val stringResource = androidContext.getString(R.string.app_name)
    
    Text(text = stringResource)
}

2. Android View Context через LocalContext

LocalContext.current предоставляет доступ к классическому Android Context (обычно Activity), который необходим для:

  • Доступа к ресурсам (getString(), getColor())
  • Запуска Activity или Services
  • Работы с System Services (локация, аудио)
  • Использования View-based компонентов (WebView, MapView)
@Composable
fun LaunchActivityButton() {
    val context = LocalContext.current
    
    Button(onClick = {
        val intent = Intent(context, DetailActivity::class.java)
        context.startActivity(intent)
    }) {
        Text("Открыть Activity")
    }
}

Ключевые CompositionLocal для контекстных данных

Jetpack Compose предоставляет несколько стандартных CompositionLocal:

  • LocalContext: доступ к Android Context
  • LocalConfiguration: информация о устройстве (ориентация, плотность пикселей)
  • LocalDensity: для конвертации пикселей в DP и SP
  • LocalFontFamily: шрифты текущей темы
  • LocalViewModelStoreOwner: для получения ViewModel

Как создавать собственный Context?

Для создания специфичного контекста вашего приложения используйте CompositionLocalProvider:

// Создание собственного CompositionLocal
val LocalUserSession = compositionLocalOf<UserSession> { error("UserSession не предоставлен") }

@Composable
fun AppRoot(userSession: UserSession) {
    CompositionLocalProvider(LocalUserSession provides userSession) {
        // Все composable внутри этого блока могут получить userSession
        MainScreen()
    }
}

@Composable
fun MainScreen() {
    val session = LocalUserSession.current // Доступ к контексту пользователя
    Text(text = "Привет, ${session.userName}")
}

Различия с традиционным Android Context

  1. Неявная передача: в Compose контекст передается неявно через дерево композиции, не требуя явной передачи параметров.
  2. Локализация: каждый CompositionLocal имеет область действия ограниченную CompositionLocalProvider.
  3. Безопасность: если значение не предоставлено, composable не сможет его получить (вызовет ошибку или default).
  4. Многопоточность: Compose Context безопасен в рамках композиции, но традиционный LocalContext.current требует осторожности при использовании вне UI-потока.

Практическое применение Context

Доступ к ресурсам

@Composable
fun ResourceText(resId: Int) {
    val context = LocalContext.current
    val text = context.resources.getString(resId)
    Text(text)
}

Адаптация к конфигурации устройства

@Composable
fun AdaptiveLayout() {
    val configuration = LocalConfiguration.current
    
    if (configuration.screenWidthDp > 600) {
        WideScreenLayout()
    } else {
        CompactScreenLayout()
    }
}

Работа с Density

@Composable
fun PixelConverter() {
    val density = LocalDensity.current
    val dpValue = 16.dp
    val pxValue = with(density) { dpValue.toPx() }
    // Использование pxValue для точных вычислений
}

Best Practices использования Context

  1. Минимизация зависимости от Android Context: предпочитайте параметры composable-функций вместо прямого использования LocalContext.
  2. Осторожность с побочными эффектами: операции с Context (запуск Activity, доступ к файлам) должны быть в контролированных побочных эффектах (LaunchedEffect, rememberCoroutineScope).
  3. Тестируемость: использование CompositionLocalProvider в тестах для предоставления mock-контекста.
  4. Избегайте хранения Context: не сохраняйте LocalContext.current в переменных с длительным сроком жизни вне композиции.

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

@Composable
fun SettingsScreen() {
    val context = LocalContext.current
    val density = LocalDensity.current
    val configuration = LocalConfiguration.current
    
    Column {
        Text(
            text = context.getString(R.string.settings),
            fontSize = with(density) { 18.sp }
        )
        
        if (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            LandscapeSettings()
        } else {
            PortraitSettings()
        }
    }
}

В итоге, Context в Jetpack Compose — это не единый объект, а система CompositionLocal, которая предоставляет доступ к различным контекстным данным, включая традиционный Android Context, но с более декларативным и безопасным подходом, соответствующим философии Compose.