Как внутри Compose функции получить контекст
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Получение контекста внутри Composable-функций
В Jetpack Compose получение контекста (Context) осуществляется через специальные механизмы, которые отличаются от традиционного подхода в View-системе. Вот основные способы:
1. LocalContext.current (наиболее рекомендуемый способ)
Этот способ использует систему Local Composition — механизм передачи зависимостей через композицию. LocalContext предоставляет текущий Context как часть окружения Composable-
функций.
@Composable
fun MyComposable() {
val context = LocalContext.current
Button(onClick = {
Toast.makeText(context, "Hello Compose!", Toast.LENGTH_SHORT).show()
}) {
Text("Показать Toast")
}
}
Важно: LocalContext.current предоставляет контекст текущего Composable, который может быть:
Activity(если вызывается внутри Activity)Application(в других случаях)
2. CompositionLocalProvider для кастомного контекста
Вы можете создать собственный CompositionLocal для передачи специализированного контекста:
val LocalCustomContext = staticCompositionLocalOf<CustomContext> {
error("CustomContext not provided")
}
@Composable
fun App() {
val customContext = remember { CustomContext() }
CompositionLocalProvider(LocalCustomContext provides customContext) {
ChildComposable()
}
}
@Composable
fun ChildComposable() {
val customContext = LocalCustomContext.current
// Используем customContext
}
3. Ambient (устаревший способ, используйте CompositionLocal)
В ранних версиях Compose использовался термин Ambient, который был заменен на CompositionLocal:
// УСТАРЕЛО - НЕ ИСПОЛЬЗУЙТЕ!
@Composable
fun DeprecatedWay() {
val context = AmbientContext.current // Теперь это LocalContext
}
4. remember с ActivityResultRegistry (для специальных случаев)
Для работы с ActivityResultLauncher или другими компонентами, требующими Activity-контекста:
@Composable
fun ActivityResultExample() {
val context = LocalContext.current
val launcher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) { result ->
// Обработка результата
}
// Использование launcher
}
5. Проблемы и ограничения при получении контекста
Важные предупреждения:
- Не сохраняйте контекст в remember без причины: Контекст может меняться (например, при смене конфигурации)
// ПЛОХО - может привести к утечке памяти
@Composable
fun WrongWay() {
val context = remember { LocalContext.current } // ❌
}
// ХОРОШО - получаем текущий контекст при каждом вызове
@Composable
fun CorrectWay() {
val context = LocalContext.current // ✅
}
- Используйте правильный тип контекста: Для разных задач нужен разный контекст:
ActivityдляstartActivity(), диалоговApplicationдля долгоживущих операцийUI Contextдля работы с ресурсами
6. Практический пример с несколькими способами
@Composable
fun ContextUsageExamples() {
// Основной способ
val context = LocalContext.current
Column {
// Пример с Toast
Button(onClick = {
Toast.makeText(context, "Сообщение", Toast.LENGTH_SHORT).show()
}) {
Text("Toast")
}
// Пример с ресурсами
Text(
text = context.getString(R.string.app_name),
color = Color(context.getColor(R.color.primary))
)
// Пример с SharedPreferences
Button(onClick = {
val prefs = context.getSharedPreferences("app", Context.MODE_PRIVATE)
prefs.edit().putString("key", "value").apply()
}) {
Text("Сохранить в Prefs")
}
}
}
7. Лучшие практики
- Используйте LocalContext.current как основной способ
- Избегайте долгоживущих ссылок на контекст в remember
- Для View-интеропов используйте
AndroidViewс правильным контекстом:
@Composable
fun WebViewExample(url: String) {
AndroidView(
factory = { context ->
WebView(context).apply {
loadUrl(url)
}
}
)
}
- Для тестирования мокируйте LocalContext через
CompositionLocalProvider
@Composable
fun TestableComposable(context: Context = LocalContext.current) {
// Более тестируемая версия
}
Получение контекста в Compose стало более декларативным и безопасным благодаря системе CompositionLocal, которая обеспечивает явную передачу зависимостей и упрощает тестирование ваших Composable-
функций.