Introduction to Jetpack Compose and Migrating RecylerView to Lazy List

Pandiyan Mani
6 min readMay 5, 2024

Jetpack Compose is a modern toolkit for building native Android UI. When the data changes or is updated then the framework automatically recalls these functions and updates the view for you.

Benefits of Using Jetpack Compose:

  • Easy to maintain: As the codebase of any application is present in a single file. It becomes easy to manage and handle the codebase of the application.
  • Declarative: It is fully declarative so that you can describe your UI components by calling some predefined functions.

Jetpack Compose has several advantages over XML:

Simplified animations :

  • Jetpack Compose has built-in support for common animations, while XML views require additional XML attributes and separate animation files.

Less boilerplate code:

  • Jetpack Compose reduces the amount of code needed to create UI layouts and handle UI events.

Automatic UI updates:

  • Jetpack Compose is designed for performance and offers automatic UI updates and optimizations.
@Composable
fun MainScreen() {
var count by remember { mutableStateOf(0) }Column(
horizontalAlignment = Alignment.Center,
verticalArrangment = Arrangement.Center
) {
Text(text = count.toString())
Spacer(modifier = Modifier.height(16.dp))
Button(onClick = { count++ }) {
Text(text = "Click me")
}
}
}
}

And in future Google will create new components which is possible to render only if you use Jetpack Compose.

Migrating RecylerView to Lazy List

Step 1: Create the app:

Open latest Android Studio -> new project -> choose “Empty Compose Activity” -> type [your project’s name].

Step 2: Add fake data for the display:

First, create a Plant data class that has an ID, a name, a description, and an image resource. The image resource will be an integer type because we will be referencing the ID of the picture using R class.

Start creating the data class by adding a new Kotlin class/file -> data class -> Plant. The data class should contain the following code:

package com.example.recylerviewinjetpack.data

data class Plant(val id: Int, val name: String, val description: String, val imageRes: Int)

Data classes in Kotlin are primarily used to hold data.

Step 3: UI development

Let’s get back to the “MainActivity” and remove the “Greeting” function and its calls from the app theme and the preview function.

Call “DisplayPlants” Composable which you will declare in a moment. Pass the “plantsList” inside “DisplayPlants”. It would look something like this:

package com.example.recylerviewinjetpack

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.example.recylerviewinjetpack.ui.theme.RecylerViewInJetPackTheme

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
RecylerViewInJetPackTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
DisplayPlants(plantsList)
}
}
}
}
}

what is Composable function?

Composable functions can only be called from other composable functions. Jetpack Compose uses a Kotlin compiler plugin to transform these composable functions into the app’s UI elements. For example, the Text composable function that is defined by the Compose UI library displays a text label on the screen .A composable function is a modern way of developing UI in Android. It is a Kotlin function that is annotated with “@Composable”.

Step 4:

Add a new Kotlin class/file -> file -> DisplayPlants

Inside that file, write “DisplayPlants” composable function which takes a list of Plants to be displayed later using LazyColumn. For now, your code should be like this:

package com.example.recylerviewinjetpack.ui.theme

import androidx.compose.runtime.Composable
import com.example.recylerviewinjetpack.data.Plant

@Composable
fun DisplayPlants(plantList: List<Plant>) {
}

For this application, we want a normal app bar displaying the app name. Then, under it, we want a list of plants with their information.

To make this, let’s use “Scaffold” composable which allows us to divide the screen into an app bar and a body content.

Scaffold composable takes a topBar parameter which can be a Composable function. For that, use the predefined TopAppBar composable function which also takes parameters to control what and how to display it.

Now that the app bar is ready, let’s move to the body content under it. For the body content, we will define a title item and a list of plant items.

For displaying a long list of items it’s recommended to use LazyColumn or LazyRow. For our case, we want to present our list vertically so we will use LazyColumn.

We want this list to take as much space available after the padding so we’ll set the width to be fillMaxWidth using Modifier.

Also, we will add a 16.dp padding to the content using ContentPadding so it does not stick to the edges of the screen. Your code should look like this:

package com.example.recylerviewinjetpack.ui.theme

import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.example.recylerviewinjetpack.data.Plant

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DisplayPlants(platList: List<Plant>) {
Scaffold(topBar = { AddAppBar() }, content = { padding ->
Surface(
modifier = Modifier.padding(padding),
) {
LazyColumn(modifier = Modifier.fillMaxWidth(), contentPadding = PaddingValues(16.dp)) {

}
}
})
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AddAppBar() {
TopAppBar(
title = { Text("Welcome To Plant List") }
)
}

You can add any number of children to a row, and they will be laid out horizontally in the order they were added.Inside Row, we should specify a Text to display a title before the plants list.

item {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 25.dp)
) {
Text(
"\uD83C\uDF3F Plants in Cosmetics",
fontStyle = FontStyle.Italic,
color = Color.Black
)
}
}

In addition to item inside LazyColumn, we can define items which takes a data list and display each list element into a composable. We will pass the plant list coming from the MainActivity as a data list for items().

Inside PlantCard, we need to pass the plant name, description, and image so we can display them. After applying what we mentioned, your code should look like this:

package com.example.recylerviewinjetpack.ui.theme

import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.unit.dp
import com.example.recylerviewinjetpack.data.Plant

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DisplayPlants(platList: List<Plant>) {
Scaffold(topBar = { AddAppBar() }, content = { padding ->
Surface(
modifier = Modifier.padding(padding),
) {
LazyColumn(modifier = Modifier.fillMaxWidth(), contentPadding = PaddingValues(16.dp)) {
item {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 25.dp)
) {
Text(
"\uD83C\uDF3F Plants in Cosmetics",
fontStyle = FontStyle.Italic,
color = Color.Black
)
}
}
item(platList) { plant->
PlantCard(plant.name, plant.description, plant.imageRes)
}
}
}
})
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AddAppBar() {
TopAppBar(title = { Text("Welcome To Plant List") })
}

Add a new Kotlin class/file -> file -> PlantCard

Inside that file, write “PlantCard” composable function with the parameters we passed previously in DisplayPlant file. Like this:

package com.example.recylerviewinjetpack

import androidx.compose.runtime.Composable

@Composable
fun PlantCard(name: String, description: String, image: Int) {}

Set the appearance for this card.we can convert the Card content into a Row() with an Image() and a column(). The column displays two texts vertically -the name and the description of the plant.

Adding a contentDescription is a must for accessibility.

We also have to specify the size of the image to ensure it’s displayed correctly. Let’s give it a 130.dp size and an 8.dp padding using Modifier.

contentScale should be FIT to display the whole image inside the defined size.

Next to the Image, we want to present text vertically using a Column composable with 8.dp padding using Modifier.

Then, add a Text composable which takes the plant name and plant description.

package com.example.recylerviewinjetpack


import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp

@Composable
fun PlantCard(name: String, description: String, image: Int) {
Card(
modifier = Modifier
.padding(10.dp)
.fillMaxWidth()
.wrapContentHeight(),
border = BorderStroke(width = 2.dp, color = Color.Black),
shape = RoundedCornerShape(size = 16.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
) {
Image(
painter = painterResource(id = image),
contentDescription = null,
modifier = Modifier
.size(130.dp)
.padding(8.dp),
contentScale = ContentScale.Fit,
)
Column(Modifier.padding(8.dp)) {
Text(
text = name,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onPrimary,
)
Text(
text = description,
style = MaterialTheme.typography.bodyMedium,
)
}
}
}
}

Result

This is the final result for this application

Entire App Code can find on the below link:

https://drive.google.com/file/d/1RrlrvDoCt6ic4Gq3VPIXp_jPAzPuSGYx/view?usp=sharing

--

--