5. Implement UI with Jetpack Compose
--
Step 1: Project Setup
First, update your libs.versions.toml
and build.gradle.kts
files to include the necessary dependencies for Jetpack Compose and ViewModel.
1.1 Update libs.versions.toml
Add the following versions and libraries to your libs.versions.toml
file:
…/gradle/libs.versions.toml
[versions]
...
lifecycleViewModelCompose = "2.8.1"
[libraries]
...
androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycleViewModelCompose" }
Adding lifecycleViewModelCompose
allows us to use Jetpack Compose with ViewModel integration.
1.2 Update build.gradle.kts
Include the ViewModel Compose dependency in your build configuration.
…/androidApp/build.gradle.kts
dependencies {
...
// ViewModel Compose
implementation(libs.androidx.lifecycle.viewmodel.compose)
}
This integrates the ViewModel with Jetpack Compose, allowing us to manage UI-related data in a lifecycle-conscious way.
Step 2: Create ViewModel
Implement a ViewModel to handle user data operations.
…/presentation/MainViewModel.kt
class MainViewModel(private val repository: UserRepository) : ViewModel() {
val allUsers: Flow<List<User>> = repository.allUsers
fun insert(user: User) = viewModelScope.launch {
repository.insert(user)
}
fun update(user: User) = viewModelScope.launch {
repository.update(user)
}
fun delete(user: User) = viewModelScope.launch {
repository.delete(user)
}
fun deleteAll() = viewModelScope.launch {
repository.deleteAll()
}
}
The ViewModel holds and manages UI-related data. It interacts with a UserRepository
to perform CRUD operations on user data.
Step 3: Register ViewModel in DI Framework
Register the MainViewModel
in your dependency injection module.
…/di/AppModule.kt
val appModule = module {
...
viewModel { MainViewModel(get()) }
}
This step ensures that your ViewModel is provided by the dependency injection framework, making it available for use in your MainActivity
.
Step 3: Update MainActivity
Use the ViewModel in your activity to observe data and update the UI.
…/presentation/MainActivity.kt
class MainActivity : ComponentActivity() {
private val viewModel by viewModel<MainViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MigrationToCmpTheme {
Surface(modifier = Modifier.fillMaxSize()) {
val users by viewModel.allUsers.collectAsState(initial = emptyList())
UserScreen(
users = users,
insert = { viewModel.insert(it) },
update = { viewModel.update(it) },
delete = { viewModel.delete(it) },
deleteAll = { viewModel.deleteAll() }
)
}
}
}
}
}
This code sets up the activity to use the ViewModel. It observes the list of users and passes them to the UserScreen
composable function, which updates the UI based on the data.
Step 4: Create User Interface with Jetpack Compose
Design the UI to display and manage users.
@Composable
fun UserScreen(
users: List<User>,
insert: (User) -> Unit,
update: (User) -> Unit,
delete: (User) -> Unit,
deleteAll: () -> Unit
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(32.dp)
) {
Button(onClick = {
val userName = (1..10).map { ('a'..'z').random() }.joinToString("")
insert(User(name = userName))
}) {
Text(text = "Add User")
}
Button(onClick = {
if (users.isNotEmpty()) {
update(User(id = users[0].id, name = "Updated ${users[0].name}"))
}
}) {
Text(text = "Update First User")
}
Button(onClick = {
if (users.isNotEmpty()) {
delete(users[0])
}
}) {
Text(text = "Delete First User")
}
Button(onClick = { deleteAll() }) {
Text(text = "Delete All Users")
}
LazyColumn(modifier = Modifier.weight(1f)) {
items(users) { user ->
Text(text = user.name, style = MaterialTheme.typography.titleLarge)
}
}
}
}
This composable function defines the UI layout and functionality for managing users. It includes buttons for adding, updating, deleting, and listing users.
Step 5: Preview the UI
Preview the composable function to see how the UI looks without running the app on a device.
@Preview(showBackground = true, showSystemUi = true)
@Composable
fun DefaultPreview() {
MigrationToCmpTheme {
UserScreen(
users = listOf(User(name = "User 1"), User(name = "User 2")),
insert = {},
update = {},
delete = {},
deleteAll = {}
)
}
}
The preview function helps you visualize the UI during development. It sets up a mock environment to display the UserScreen
composable with sample data.
Step 6: Build and Run the App
The screenshot and gif: