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

Как бы сделал LocalContext.current

3.0 Senior🔥 141 комментариев
#Kotlin основы#UI и вёрстка#Архитектура и паттерны

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

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

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

Использование LocalContext.current в Compose

LocalContext.current — это CompositionLocal, который предоставляет доступ к контексту Android в любой точке дерева Compose. В отличие от традиционного подхода с передачей контекста через параметры, он позволяет получать контекст "неявно", что упрощает код, но требует осторожности.

Основной подход

@Composable
fun MyScreen() {
    val context = LocalContext.current
    
    Column {
        Button(
            onClick = {
                // Использование контекста для Toast
                Toast.makeText(context, "Нажато!", Toast.LENGTH_SHORT).show()
            }
        ) {
            Text("Показать Toast")
        }
        
        // Доступ к ресурсам через контекст
        Text(text = stringResource(R.string.app_name))
    }
}

Ключевые аспекты использования

  1. Ленивое получение контекста Контекст следует получать только тогда, когда он действительно нужен, а не декларативно на верхнем уровне:
// ПЛОХО - контекст получен декларативно, но может не использоваться
@Composable
fun MyComposable() {
    val context = LocalContext.current
    // ... много кода, где контекст не используется
}

// ХОРОШО - контекст получен только при необходимости
@Composable
fun MyComposable() {
    Button(onClick = {
        val context = LocalContext.current
        Toast.makeText(context, "Сообщение", Toast.LENGTH_SHORT).show()
    }) {
        Text("Кнопка")
    }
}
  1. Использование в обработчиках событий Контекст часто нужен в обработчиках onClick, onValueChange и других событиях:
@Composable
fun IntentLauncher() {
    val context = LocalContext.current
    
    Button(onClick = {
        val intent = Intent(context, DetailsActivity::class.java)
        context.startActivity(intent)
    }) {
        Text("Открыть детали")
    }
}
  1. Доступ к ресурсам Для большинства операций с ресурсами есть специальные Compose-функции:
@Composable
fun ResourceExample() {
    // Вместо context.resources.getString(R.string.app_name)
    val appName = stringResource(id = R.string.app_name)
    
    // Вместо context.resources.getColor(R.color.primary)
    val primaryColor = colorResource(id = R.color.primary)
}

Альтернативы и лучшие практики

1. Явная передача зависимостей

Для бизнес-логики предпочтительнее явная передача:

@Composable
fun UserProfile(
    viewModel: UserViewModel, // Зависимости передаются явно
    onNavigate: () -> Unit
) {
    // Вместо использования LocalContext.current внутри ViewModel
}

2. ViewModel с SavedStateHandle

Для доступа к контексту в ViewModel используйте AndroidViewModel:

class MyViewModel(application: Application) : AndroidViewModel(application) {
    val context: Context get() = getApplication<Application>().applicationContext
    
    fun doSomething() {
        // Использование контекста
    }
}

3. Провайдеры для тестирования

Для тестируемости инкапсулируйте операции, требующие контекста:

class ResourceProvider(private val context: Context) {
    fun getString(@StringRes resId: Int): String = context.getString(resId)
}

@Composable
fun TestableComposable(resourceProvider: ResourceProvider) {
    Text(text = resourceProvider.getString(R.string.app_name))
}

Предостережения

  • Не храните контекст в состоянии или переменных - это может привести к утечкам памяти
  • Избегайте использования в лямбдах с длинным сроком жизни - контекст может стать невалидным
  • Для Application Context используйте LocalContext.current.applicationContext
  • Внимание к пересозданию - при повороте экрана контекст изменится

Вывод

LocalContext.current — мощный инструмент, но использовать его следует осознанно. Основные правила:

  • Получайте контекст как можно ближе к месту использования
  • Предпочитайте явную передачу зависимостей для бизнес-логики
  • Используйте специальные Compose-функции для работы с ресурсами
  • Избегайте сохранения контекста в переменных с длительным временем жизни

Правильное использование LocalContext.current делает код Compose более чистым и поддерживаемым, сохраняя при этом тестируемость и безопасность относительно жизненного цикла.

Как бы сделал LocalContext.current | PrepBro