Introdução: Por que o Context no Jetpack Compose é uma dor de cabeça para iniciantes?
\nSe você já escreveu para Android usando XML, sabe que o Context é literalmente a "chave" para tudo: desde acesso a recursos até iniciar novas Activities. Mas quando você migra para o Jetpack Compose, tudo muda. As funções compostas não têm acesso direto ao Context, e isso frequentemente se torna um ponto de tropeço para desenvolvedores, especialmente aqueles que estão começando a aprender a abordagem declarativa.
A pergunta "How to get Context in Jetpack Compose" no Stack Overflow acumulou milhares de visualizações e dezenas de respostas. Isso não é por acaso. Neste artigo, vamos abordar todas as formas possíveis de obter o Context no Compose, desde as simples até as avançadas, com exemplos reais de código em Kotlin. Você aprenderá quando usar LocalContext.current, como evitar vazamentos de memória e quais práticas são consideradas "best practices" em 2025.
1. A maneira mais simples: LocalContext.current
\nSe você precisa obter o Context dentro de uma função composta, a maneira mais direta é usar LocalContext.current. Este é um composable-local que fornece o Context atual (geralmente uma Activity ou ContextWrapper).
@Composable\nfun MyScreen() {\n val context = LocalContext.current\n \n Button(onClick = {\n Toast.makeText(context, "Olá do Compose!", Toast.LENGTH_SHORT).show()\n }) {\n Text("Mostrar Toast")\n }\n}\n\nEste código funciona, mas há uma nuance: LocalContext.current fornece um Context vinculado ao CompositionLocal atual. Na maioria dos casos, é o que você precisa. No entanto, lembre-se de que esse Context não deve ser passado para uma ViewModel ou armazenado em objetos de longa duração — isso pode causar vazamentos de memória.
Quando usar isso?
\n- \n
- Para ações únicas na UI: Toast, Snackbar, iniciar Activity. \n
- Para acessar recursos:
context.getString(R.string.app_name). \n - Para trabalhar com serviços do sistema:
context.getSystemService(). \n
2. Context na ViewModel: A abordagem correta
\nUm dos erros mais comuns é passar o Context diretamente para a ViewModel. No Android Architecture Components, isso é considerado um antipadrão, pois a ViewModel pode sobreviver à Activity, e o Context se tornará obsoleto. Em vez disso, use AndroidViewModel.
class MyViewModel(application: Application) : AndroidViewModel(application) {\n \n private val context = getApplication<Application>().applicationContext\n \n fun loadData() {\n // Usamos applicationContext, que é seguro\n val prefs = context.getSharedPreferences("my_prefs", Context.MODE_PRIVATE)\n }\n}\n\nNo Compose, você pode obter uma instância dessa ViewModel da maneira padrão:
\n\n@Composable\nfun MyScreen() {\n val viewModel: MyViewModel = viewModel()\n // Context já está dentro da ViewModel, não precisa passar da UI\n}\n\nVantagem: O applicationContext vive enquanto o processo estiver ativo e não depende do ciclo de vida da Activity. Isso é seguro e recomendado pelo Google.
3. Context no CompositionLocal: Provedores personalizados
\nÀs vezes, você precisa passar um Context específico (por exemplo, para testes ou para um módulo com biblioteca). Nesses casos, você pode criar seu próprio CompositionLocal.
val LocalCustomContext = staticCompositionLocalOf<Context> {\n error("Nenhum contexto personalizado fornecido")\n}\n\n@Composable\nfun CustomContextProvider(context: Context, content: @Composable () -> Unit) {\n CompositionLocalProvider(LocalCustomContext provides context) {\n content()\n }\n}\n\n// Uso:\n@Composable\nfun MyScreen() {\n val customContext = LocalCus