Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Kickstart Modern Android Development with Jetpack and Kotlin

You're reading from   Kickstart Modern Android Development with Jetpack and Kotlin Enhance your applications by integrating Jetpack and applying modern app architectural concepts

Arrow left icon
Product type Paperback
Published in May 2022
Publisher Packt
ISBN-13 9781801811071
Length 472 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Catalin Ghita Catalin Ghita
Author Profile Icon Catalin Ghita
Catalin Ghita
Arrow right icon
View More author details
Toc

Table of Contents (17) Chapters Close

Preface 1. Part 1: Exploring the Core Jetpack Suite and Other Libraries
2. Chapter 1: Creating a Modern UI with Jetpack Compose FREE CHAPTER 3. Chapter 2: Handling UI State with Jetpack ViewModel 4. Chapter 3: Displaying Data from REST APIs with Retrofit 5. Chapter 4: Handling Async Operations with Coroutines 6. Chapter 5: Adding Navigation in Compose With Jetpack Navigation 7. Part 2: A Guide to Clean Application Architecture with Jetpack Libraries
8. Chapter 6: Adding Offline Capabilities with Jetpack Room 9. Chapter 7: Introducing Presentation Patterns in Android 10. Chapter 8: Getting Started with Clean Architecture in Android 11. Chapter 9: Implementing Dependency Injection with Jetpack Hilt 12. Chapter 10: Test Your App with UI and Unit Tests 13. Part 3: Diving into Other Jetpack Libraries
14. Chapter 11: Creating Infinite Lists with Jetpack Paging and Kotlin Flow 15. Chapter 12: Exploring the Jetpack Lifecycle Components 16. Other Books You May Enjoy

Exploring lists with Compose

In the previous section, we built a Compose-based screen that features a list of restaurants. However, if you run the application or preview the screen in interactive mode, you will notice that the list doesn't scroll. This is a huge inconvenience that we will address in this section by adding scroll capabilities to our Column composable.

Next, we will specify why Column is suited for static content, whereas if the list is large and its size is dynamic or dictated by the server's response, we should use lazy composables. We will explore a variety of lazy composables and understand why they are better suited for large lists.

To summarize, this section will cover the following topics:

  • Adding scrolling to the Column composable
  • Introducing lazy composables
  • Using LazyColumn to display restaurants

Let's start by adding scrolling capabilities to our RestaurantsScreen composable.

Adding scrolling to the Column composable

Our list of restaurants is long, and it can't scroll. This is a bad user experience, so let's fix it.

Let's make the Column scrollable by passing a Modifier.verticalScroll modifier that receives a ScrollState:

@Composable
fun RestaurantsScreen() {
   Column(Modifier.verticalScroll(rememberScrollState())) {
       ...
   }
}

We want the scrolling position to be retained across recompositions. That's why, by passing rememberScrollState to the verticalScroll modifier, we ensure that every time the UI recomposes, the scroll state is remembered and retained. The rememberScrollState persistence mechanism is similar to the remember { } block, which we used previously to retain the TextField's state across recompositions.

Now, you can Run the app or preview it in Interactive mode and check out the scrolling effect.

However, we have one final issue with our Column that is related to how Column lays and composes its elements. Let's dive into that now and try to find a better alternative.

Introducing lazy composables

Let's take a short break from our restaurant app and try to think of a better way of handling large lists. Using Row or Column for displaying long lists of items, or maybe a list of unknown size, can prove detrimental to your UI and impact your app's performance. This happens because Row and Column render or lay all their children out, whether they are visible or not. They are good for displaying static content, yet passing a large list can cause your UI to become laggy or even unusable.

Two lazy composables called LazyColumn and LazyRow come to your rescue since they only compose or output those items that are currently visible on the screen, hence the term lazy. So, as you can see, they are somehow similar to the old RecyclerView.

As the only difference between Row and Column was the way children were laid out on the screen – horizontally or vertically – the same thing applies with LazyRow and LazyColumn. These lazy composables lay their children out horizontally or vertically and provide scrolling capabilities out of the box. As they only render the visible items, lazy composables are a much better fit for large lists.

Yet, lazy composables are different than the regular composables that we've used so far. That's mainly because instead of accepting @Composable content, they expose a domain-specific language (DSL) defined by a LazyListScope block:

@Composable
fun LazyColumn(
   ...
   content: LazyListScope.() -> Unit
) { … }

The LazyListScope DSL allows us to describe the item contents that we want to be displayed as part of the list. The most commonly used ones are item() and items(). Such example usage of LazyColumn that makes use of DSL is as follows:

LazyColumn {
   item() {
       Text(text = "Custom header item")
   }
   items(myLongList) { myItem ->
       MyComposable(myItem)
   }
   item(2) {
       Text(text = "Custom footer item")
   }
}

item() adds a single composable element to the list, while items() can receive not only a standalone list of content such as myLongList but also an Int, which will add the same item multiple times.

The code that we featured previously should render a vertical list that contains the following:

  • A header Text composable
  • A list of MyComposable composables that are the same size as myLongList
  • Two Text footer composables

Returning from the DSL world, a noteworthy argument for the lazy composables is contentPadding, which allows you to define horizontal/vertical padding surrounding your list. This argument expects a PaddingValues object – we will use it soon; don't worry!

Now, we will soon receive the restaurants from a remote server, which means we don't know the size of the list, so it's time to implement such a lazy composable in our Restaurants application as well.

Using LazyColumn to display restaurants

We are currently using Column to display our dummyRestaurants list. We know why that's not the best practice, so to optimize our UI for dynamic content, we will replace it with LazyColumn so that we can continue displaying the restaurants vertically.

Go back to the RestaurantsScreen.kt file and, inside of the RestaurantScreen composable, replace the Column composable with LazyColumn:

@Composable
fun RestaurantsScreen() {
   LazyColumn(
       contentPadding = PaddingValues(
           vertical = 8.dp,
           horizontal = 8.dp)) {
       items(dummyRestaurants) { restaurant ->
           RestaurantItem(restaurant)
       }
   }
}

We've used its DSL and specified the items properties that should populate our LazyColumn by passing the dummyRestaurants list. We obtained access to each item as a restaurant of type Restaurant and rendered it through a RestaurantItem composable.

We also added additional padding through the contentPadding argument to our LazyColumn by passing a PaddingValues object where we configured the vertical and horizontal padding.

You can now Run the app and check out the scrolling effect. In our case, the output is the same, yet if we were to test the app with a very long list of restaurants, we would have a much smoother scroll effect and a better UI experience with LazyColumn than with Column.

We've done it! We've built our first Compose-based app from scratch while exploring tons of composable functions. We've added a list that scrolls beautifully, and we can now be proud of the result!

You have been reading a chapter from
Kickstart Modern Android Development with Jetpack and Kotlin
Published in: May 2022
Publisher: Packt
ISBN-13: 9781801811071
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime