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 uma camada acima dessas APIs para mapear o estado concedido atual para permissões em um 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, e é retida enquanto o escopo estiver ativo.
Por exemplo, se o elemento combinável for usado em uma atividade, viewModel()
vai retornar o
na 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 ViewModel
instâncias no nível da tela
elementos combináveis, ou seja, próximos de um elemento raiz chamado de uma atividade,
fragmento ou destino de um gráfico de navegação. Isso ocorre porque ViewModel
s
têm, por padrão, o escopo desses objetos no nível da tela. Leia mais sobre um
ViewModel
ciclo de vida e escopo.
Tente evitar a transmissão
Instâncias de ViewModel
para outros elementos combináveis, já que isso pode tornar esses elementos combináveis.
mais difíceis de testar e podem falhar
prévias. Em vez disso, transmita apenas os dados
e as funções de que precisam como parâmetros.
É possível usar instâncias do ViewModel
para
gerenciar o estado para elementos combináveis no nível da subtela. No entanto, esteja ciente das
ViewModel
ciclo de vida e escopo. Se o
combinável é independente, use o Hilt para:
injetar o ViewModel
para evitar a necessidade de transmitir dependências do pai
que podem ser compostos.
Caso sua ViewModel
tenha dependências, o viewModel()
usa uma linguagem opcional
ViewModelProvider.Factory
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 Como navegar com o Compose e Para ver mais informações, migre 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.
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 = 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