Open the Starter project in the 05-leverage-components directory of the m3-cjp-materials repo in Android Studio Jellyfish or later.
Wait for the project to be built. You’ll continue working on the GithubRepo app in this lesson, but you won’t be making any functional or visual changes.
In this lesson, you’ll work on cleaning up the code and breaking up the UI using the concept of components.
Open the MainActivity.kt file.
Until now, all of your changes to build the repo list UI have been consolidated into the MainActivity, and in a way, this file has now become a god class - it’s a monolith that draws the entire UI.
In the future, if you were to extend the app further and add new features that require the the same user interface component as the repo card, you’ll have to duplicate the entire code that currently builds the list item.
Duplication of code comes with two tricky problems:
- If you needed to modify the design of the list item, you would have to do it in two places.
- If a bug needed to be fixed, you’d need to do it in two places, and there’s a chance you could forget to update all instances.
Considering how big the class has become in terms of lines of code, debugging issues or introducing further changes would also feel quite slow.
This is why it’s always best practice to break your screen down into small, reusable components that are each responsible for the rendering and behavior of one UI.
In the case of this app, the GitHub repo list item is an excellent candidate to be extracted out into its own component.
Create a new package in the root directory named components. Create a new file named GitHubRepoCard.kt.
Add the following code to the file:
@Composable
fun GitHubRepoCard(repo: GitHubRepository) {
}
Next, from the MainActivity.kt file, extract the parent Box and paste it inside the GithubRepoCard.
This is what the file should now look like:
@Composable
fun GitHubRepoCard(repo: GitHubRepository) {
Box {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(16.dp)
) {
AsyncImage(
modifier = Modifier
.size(75.dp)
.clip(CircleShape),
model = repo.owner.avatarUrl,
contentDescription = null,
)
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Text(
text = repo.name,
fontSize = 16.sp,
fontWeight = FontWeight.Bold
)
Spacer(modifier = Modifier.height(8.dp))
repo.description?.let {
Text(text = it, fontSize = 14.sp)
}
Spacer(modifier = Modifier.height(8.dp))
Text(
text = repo.htmlUrl,
fontWeight = FontWeight.Normal,
textDecoration = TextDecoration.Underline
)
}
}
}
}
Finally, in the MainActivity, use the newly created GitHubRepoCard component as follows:
setContent {
val state by viewModel.state.observeAsState()
Column(modifier = Modifier.padding(16.dp)) {
state?.forEach { repo ->
GitHubRepoCard(repo)
Spacer(modifier = Modifier.height(16.dp))
}
}
}
Build and run the app. The UI should look the same but now you have modularized the UI and introduced reusability. While the change feels trivial in the context of this demo app, when used in larger projects it often introduces a lot of flexibility, reuse and consolidation of logic.
That concludes this demo. Continue with the lesson for a summary.