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 sua IU 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 seguinte dependência ao arquivo do Gradle:
Groovy
dependencies { implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.8.5' }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.5") }
Em seguida, use a função viewModel()
no código.
class MyViewModel : ViewModel() { /*...*/ } // import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( viewModel: MyViewModel = viewModel() ) { // use viewModel here }
A viewModel()
retorna um ViewModel
já existente ou cria um novo. Por padrão,
o ViewModel
retornado é aplicado à atividade, ao fragmento ou ao
destino de navegação que o contém e é mantido enquanto o escopo estiver ativo.
Por exemplo, se o elemento combinável for usado em uma atividade, a função 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
Normalmente, você acessa instâncias ViewModel
em elementos combináveis
no nível da tela, ou seja, próximos a um elemento raiz chamado de uma atividade, fragmento ou destino de um gráfico de navegação. Isso ocorre porque os ViewModel
s
são, por padrão, de escopo para esses objetos de nível de tela. Leia mais sobre o
ciclo de vida e o escopo de um
ViewModel
.
Evite transmitir
instâncias do ViewModel
para outros elementos combináveis, porque isso pode dificultar o teste deles e quebrar
visualizações. Em vez disso, transmita apenas os dados
e as funções que eles precisam como parâmetros.
Você pode usar instâncias de ViewModel
para
gerenciar o estado de elementos combináveis no
nível da subtela. No entanto, observe o
ciclo de vida e o escopo
de ViewModel
. Se o
combinável for independente, considere usar o Hilt para
injetar o ViewModel
e evitar a necessidade de transmitir dependências de elementos
combináveis principais.
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. Consulte Navegar com o Compose e Migrar a navegação do Jetpack para o Navigation Compose para mais informações.
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.2.0' }
Kotlin
dependencies { implementation("androidx.hilt:hilt-navigation-compose:1.2.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.
Maps
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 = remember { 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