Você pode usar suas bibliotecas favoritas no Compose. Nesta seção, descrevemos como incorporar algumas das bibliotecas mais úteis.
Atividade
Para usar o Compose em uma atividade, use a
ComponentActivity
,
uma subclasse de Activity
que fornece o LifecycleOwner
e os
componentes adequados para o Compose. Ela fornece também outras APIs que separam o código
da substituição de métodos na sua classe de atividade.
O Activity Compose
expõe essas APIs a elementos que podem ser compostos, de modo que a substituição de métodos fora desses
elementos ou a recuperação de uma instância Activity
explícita não seja mais necessária.
Além disso, as APIs garantem que elas sejam inicializadas apenas uma vez, sobrevivam
à recomposição e sejam apagadas adequadamente quando o elemento combinável é removido da
composição.
Resultado da atividade
A
API rememberLauncherForActivityResult()
permite que você
receba o resultado de uma atividade
no elemento combinável:
@Composable fun GetContentExample() { var imageUri by remember { mutableStateOf<Uri?>(null) } val launcher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? -> imageUri = uri } Column { Button(onClick = { launcher.launch("image/*") }) { Text(text = "Load Image") } Image( painter = rememberAsyncImagePainter(imageUri), contentDescription = "My Image" ) } }
O exemplo demonstra um contrato
GetContent()
simples. A solicitação será iniciada quando você tocar no botão. O lambda final de
rememberLauncherForActivityResult()
será invocado quando o usuário selecionar uma imagem e retornar à atividade de inicialização.
Essa ação carrega a imagem selecionada usando a função rememberImagePainter()
da Coil.
Qualquer subclasse de
ActivityResultContract
pode ser usada como primeiro argumento de
rememberLauncherForActivityResult()
.
Ou seja, é possível usar essa técnica para solicitar conteúdo do framework
e em outros padrões comuns. Com essa técnica, também é possível
criar e usar seus próprios
contratos personalizados.
Como solicitar permissões de execução
A mesma API Activity Result e
rememberLauncherForActivityResult()
explicadas acima podem ser usadas para
solicitar permissões de execução
usando o
contrato RequestPermission
para uma única permissão ou o
contrato RequestMultiplePermissions
para várias permissões.
A biblioteca Accompanist Permissions também pode ser usada em uma camada acima dessas APIs para mapear o estado concedido atual de permissões no estado que a interface do Compose pode usar.
Como processar o botão "Voltar" do sistema
Para fornecer uma navegação de retorno personalizada
e substituir o comportamento padrão do botão "Voltar" do sistema no
elemento combinável, o elemento pode usar um
BackHandler
para interceptar o evento:
var backHandlingEnabled by remember { mutableStateOf(true) } BackHandler(backHandlingEnabled) { // Handle back press }
O primeiro argumento controla se o
BackHandler
está ativado. Você pode usá-lo para desativar temporariamente o processador
com base no estado do componente. O lambda final será invocado se o
usuário acionar um evento de retorno do sistema enquanto o
BackHandler
estiver ativado.
ViewModel
Se você usar a biblioteca Architecture Components
ViewModel, poderá acessar um
ViewModel
em qualquer função que pode ser composta
chamando a
função
viewModel()
. Adicione a dependência abaixo ao arquivo do Gradle:
Groovy
dependencies { implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1' }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1") }
Você pode usar a função viewModel()
no seu código.
class MyViewModel : ViewModel() { /*...*/ } // import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( viewModel: MyViewModel = viewModel() ) { // use viewModel here }
viewModel()
retorna um ViewModel
existente ou cria um novo. Por padrão,
o ViewModel
retornado tem o escopo definido para a atividade, fragmento ou
destino de navegação que o envolvem e é mantido enquanto o escopo estiver ativo.
Por exemplo, se o elemento combinável for usado em uma atividade, viewModel()
vai retornar a
mesma instância até que a atividade seja concluída ou o processo seja encerrado.
class MyViewModel : ViewModel() { /*...*/ } // import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( // Returns the same instance as long as the activity is alive, // just as if you grabbed the instance from an Activity or Fragment viewModel: MyViewModel = viewModel() ) { /* ... */ } @Composable fun MyScreen2( viewModel: MyViewModel = viewModel() // Same instance as in MyScreen ) { /* ... */ }
Diretrizes de uso
Geralmente, as instâncias de ViewModel
são acessadas em elementos combináveis no nível da tela, ou seja, perto de um elemento raiz chamado de uma atividade, um fragmento ou um destino de um gráfico de navegação. Isso ocorre porque os ViewModel
s
têm, por padrão, o escopo desses objetos no nível da tela. Leia mais sobre o
ciclo de vida e o escopo
de um ViewModel
.
Evite transmitir
instâncias de ViewModel
para outros elementos combináveis, já que isso pode dificultar o teste deles
e corromper as
visualizações. Em vez disso, transmita apenas os dados
e as funções de que precisam como parâmetros.
Você pode usar instâncias ViewModel
para
gerenciar o estado de elementos combináveis no nível da subtela. No entanto, esteja ciente do
ciclo de vida e escopo
da ViewModel
. Se o
elemento combinável for autossuficiente, use o Hilt para
injetar o ViewModel
e evitar a necessidade de transmitir dependências de elementos combináveis
pais.
Se o ViewModel
tiver dependências, viewModel()
usará um
ViewModelProvider.Factory
opcional como parâmetro.
Para ver mais informações sobre ViewModel
no Compose e sobre como as instâncias são usadas
com a biblioteca Navigation Compose ou sobre atividades e fragmentos,
consulte os documentos sobre interoperabilidade.
Streams de dados
O Compose vem com extensões para as soluções mais populares com base em stream do Android. Cada uma dessas extensões é fornecida por um artefato diferente:
LiveData.observeAsState()
incluído no artefatoandroidx.compose.runtime:runtime-livedata:$composeVersion
.Flow.collectAsState()
não requer dependências extras.Observable.subscribeAsState()
incluído no artefatoandroidx.compose.runtime:runtime-rxjava2:$composeVersion
ouandroidx.compose.runtime:runtime-rxjava3:$composeVersion
.
Esses artefatos são registrados como listeners e representam os valores como
State
. Sempre que um novo valor
é emitido, o Compose faz a recomposição das partes da IU em que state.value
é
usado. Por exemplo, neste código, ShowData
faz a recomposição todas as vezes que
exampleLiveData
emite um novo valor.
// import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( viewModel: MyViewModel = viewModel() ) { val dataExample = viewModel.exampleLiveData.observeAsState() // Because the state is read here, // MyScreen recomposes whenever dataExample changes. dataExample.value?.let { ShowData(dataExample) } }
Operações assíncronas no Compose
O Jetpack Compose permite executar operações assíncronas usando corrotinas em funções que podem ser compostas.
Consulte as APIs LaunchedEffect
, produceState
e rememberCoroutineScope
na
documentação de efeitos colaterais para mais
informações.
Navegação
O componente de navegação oferece suporte a aplicativos do Jetpack Compose. Para mais informações, consulte Como navegar com o Compose e Migrar a navegação do Jetpack para o Navigation Compose.
Hilt
O Hilt é a solução recomendada para injeção de dependência em apps Android e funciona perfeitamente com o Compose.
A função viewModel()
mencionada na seção ViewModel
usa automaticamente o ViewModel criado pelo Hilt com a
anotação @HiltViewModel
. Disponibilizamos uma documentação com informações sobre a integração do
ViewModel do Hilt.
@HiltViewModel class MyViewModel @Inject constructor( private val savedStateHandle: SavedStateHandle, private val repository: ExampleRepository ) : ViewModel() { /* ... */ } // import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( viewModel: MyViewModel = viewModel() ) { /* ... */ }
Hilt e navegação
O Hilt também se integra à biblioteca Navigation Compose. Adicione as seguintes dependências a mais ao arquivo do Gradle:
Groovy
dependencies { implementation 'androidx.hilt:hilt-navigation-compose:1.0.0' }
Kotlin
dependencies { implementation("androidx.hilt:hilt-navigation-compose:1.0.0") }
Ao usar a biblioteca Navigation Compose, sempre use a função de composição hiltViewModel
para acessar uma instância do ViewModel
anotado com @HiltViewModel
.
Isso funciona com fragmentos ou atividades que incluem a anotação
@AndroidEntryPoint
.
Por exemplo, se ExampleScreen
for um destino em um gráfico de navegação,
chame hiltViewModel()
para ter uma instância de ExampleViewModel
com escopo
para o destino, como mostrado no snippet de código abaixo:
// import androidx.hilt.navigation.compose.hiltViewModel @Composable fun MyApp() { val navController = rememberNavController() val startRoute = "example" NavHost(navController, startDestination = startRoute) { composable("example") { backStackEntry -> // Creates a ViewModel from the current BackStackEntry // Available in the androidx.hilt:hilt-navigation-compose artifact val viewModel = hiltViewModel<MyViewModel>() MyScreen(viewModel) } /* ... */ } }
Se você precisar recuperar a instância de um ViewModel
com escopo para
rotas de navegação ou o
gráfico de navegação, use a função de composição hiltViewModel
e transmita a backStackEntry
correspondente como um parâmetro:
// import androidx.hilt.navigation.compose.hiltViewModel // import androidx.navigation.compose.getBackStackEntry @Composable fun MyApp() { val navController = rememberNavController() val startRoute = "example" val innerStartRoute = "exampleWithRoute" NavHost(navController, startDestination = startRoute) { navigation(startDestination = innerStartRoute, route = "Parent") { // ... composable("exampleWithRoute") { backStackEntry -> val parentEntry = remember(backStackEntry) { navController.getBackStackEntry("Parent") } val parentViewModel = hiltViewModel<ParentViewModel>(parentEntry) ExampleWithRouteScreen(parentViewModel) } } } }
Paging
A biblioteca
Paging
facilita o carregamento gradual de dados e é compatível com o Compose.
A página de lançamento
da Paging contém
informações sobre a dependência complementar paging-compose
, que precisa ser adicionada
ao projeto e à respectiva versão.
Confira um exemplo das APIs do Compose da biblioteca Paging:
@Composable fun MyScreen(flow: Flow<PagingData<String>>) { val lazyPagingItems = flow.collectAsLazyPagingItems() LazyColumn { items( lazyPagingItems.itemCount, key = lazyPagingItems.itemKey { it } ) { index -> val item = lazyPagingItems[index] Text("Item is $item") } } }
Consulte a documentação sobre listas e grades para mais informações sobre como usar a Paging no Compose.
Mapas
Você pode usar a biblioteca do Maps Compose para oferecer o Google Maps no seu app. Veja um exemplo de uso:
@Composable fun MapsExample() { val singapore = LatLng(1.35, 103.87) val cameraPositionState = rememberCameraPositionState { position = CameraPosition.fromLatLngZoom(singapore, 10f) } GoogleMap( modifier = Modifier.fillMaxSize(), cameraPositionState = cameraPositionState ) { Marker( state = MarkerState(position = singapore), title = "Singapore", snippet = "Marker in Singapore" ) } }
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Efeitos colaterais no Compose
- Estado e Jetpack Compose
- Salvar o estado da interface no Compose