Loading...
Home
  • Tech Blogs
  • Videos
  • Conferences
    • Droidcon News
    • Upcoming Conferences
    • Become a Partner
    • Past Events
    • Keep Me Informed
    • Diversity Scholarships
  • Community
    • droidcon Team
    • How to Hold a Droidcon
  • Android Careers
Sign In

Global CSS

 

How to Write Memorable Functions

Managing state with Jetpack Compose

 

 
Denis Crăciunescu
Android Developer @ iQuest
Published: September 18, 2020
Tweet
Share
 
 

 

Introduction

Jetpack Compose is a modern, fully declarative UI toolkit created to address the challenges of the old View system.

Unlike the old View system, Compose provides a declarative API that enables your UI to react to changes, without imperatively mutating the frontend views.

Conversely, the old View system requires you to manually update the nodes (views) from the View hierarchy by calling methods such as textView.setText().

The View system approach increases the likelihood of errors since the actual state of the Views is internalized. That means you have two statesfor every UI component — the state you are maintaining in our application (e.g. data stored in a ViewModel), and the internal state of the View.

 

The challenge is to keep both states in sync

 

Declarative paradigm shift

The old View system builds the UI by instantiating a tree of Views. This is often done by inflating an XML layout file.

Each View maintains its own state and provides accessors and mutators that allow the application logic to interact with the internal state of the View.

However, in Compose, views are not exposed as objects. 
Composable functions only describe the UI, and not construct it themselves.

So then, how does Jetpack Compose update its Views?

Image for post

 

Whenever the state changes, the Composable functions are called again with the new data, and the UI is redrawn. This process is called Recomposition.

 

UI is a reflection of state

 

Recomposition

The main role of a Composable function is to convert the state into UI. It does so by calling (emitting) other Composable functions that create a tree-like hierarchy stored inside a SlotTable.

SlotTable is a gap buffer implementation of the composition slot space. This implementation facilitates the Recomposition process because elements can be easily inserted and removed.

An element in the slot space can be a:

  • Slot, which is the primitive base type of the slot space. It is of type Any?and can hold any value.
  • Group, which is a keyed group of Slots. It counts the number of slots and nodes it contains. Groups represent memoized function calls.
  • Node, which is a special type of Group. Nodes represent Views.

The Compose framework can intelligently recompose only the components that changed. 
Functions that do not depend on the changed state are not recomposed.

 

Composable “memory”

The state is considered to be anything that could influence the UI, at a point in time.
You can imagine how quickly the state can change in a dynamic application.

 

 

Animations change state at every frame.
Composable functions will recompose at every frame of the animation. 
Thus, costly calculations would be computed at every frame.

To overcome this issue, complex calculations can be wrapped in a call to remember.

 

 

The remember function works as follows:

  • if the calculation was previously computed for the given inputs, then return it from the slot space
  • otherwise, compute the calculation, store it in the slot space, and return it

 

 
 

If the list of readers doesn’t change, the value of awesomeReaders will be computed only once, and it will be stored in the slot space.

Subsequent calls, during the Recomposition process, will query the slot space for the previously computed result of the calculation, and not do the calculation again.

If the list of readers changes (and hopefully it will for this article 😀), the calculation is performed again, and the result is stored in the slot space.

You can think of the remember function as a map over the slot space. You use the inputs as the key to try to retrieve the corresponding value from the slot space.

 

But functions can forget…

 

Image for post

 

Even though Compose exposes the remember mechanism, you shouldn’t always rely on it.

If a Composable function is completely removed from the slot space, you lose all data that the function “remembered”.

 

Values remembered in the slot space are forgotten when the calling composable is removed from the slot space.

 

This can easily happen in the case of LazyColumnFor because cells are destroyed when they pass the scrolling limit, and the respective calculation is recomputed when they become visible again.


Truly memorable functions

Jetpack Compose provides the State type which acts as an observable state holder. 
Composable functions can subscribe to this state and automatically recompose when the state changes.

You can declare a state object in the following ways:

 

 

It’s important to remember to remember the State object. Otherwise, it will be reinitialized with every Recomposition.

Whenever a Composable function reads the value of a state object, it automatically subscribes to the state.

 

But functions can still forget…

Even if your function remembers the state, how can you make sure that it won’t forget it?

 

Welcome back ViewModel!

 

The state can still be maintained by the ViewModel. The only difference is that you are ditching the LiveData for State.

 

 

This way, you can make sure that your state is preserved because the ViewModel is not tied to the lifecycle of a Composable function.

Compose provides delegates to ease working with State (see above example).

If you are unfamiliar with the delegation pattern in Kotlin, we invite you to read this article:

 

Don’t Reinvent the Wheel, Delegate It!

Favouring delegation to inheritance with Kotlin native support

proandroiddev.com

 

The State class works exclusively in the Compose context. It does not work in the old View system.

However, it turns out that LiveData can still be used with Compose. 
You don’t even have to touch the ViewModel if you plan to progressively migrate your application to Compose.

All you have to do is use the observeAsState() extension function to convert your LiveData to State inside Composable functions.

 

 


Conclusion

In the old View system, there are always two states — the application state and the View state. 
The challenge is to keep them in sync.

However, Jetpack Compose natively supports the concept of State. The state is no longer internalized in the views and a single source of truth is exposed.

We have seen that Composable functions have ‘memory’ and can remember certain calculations… They can also forget them.

The most reliable place to hold the state is still the ViewModel. 
If you progressively migrate your application to Compose, you might not even need to touch the ViewModel.
LiveData objects can be easily converted to State with the use of built-in extension functions.


I hope you enjoyed this article.
If you found the information useful, don’t forget to clap.

Until next time! 😀

Reach out to me on LinkedIn if you have suggestions for future articles.

 

Denis Crăciunescu — Android Developer — iQuest Group | LinkedIn

View Denis Crăciunescu’s profile on LinkedIn, the world’s largest professional community.

www.linkedin.com

 

*illustrations generated using icons8 vector creator

 

 

Tags: Android, Jetpack Compose, Kotlin, Android App Development, AndroidDev

 

View original article at: 


 

Originally published: September 15, 2020

Android News
Compose CameraX on Android
Compose CameraX on Android

By Peng Jiang

Android new UI toolkit Jetpack compose is in beta now, which has all the features you need to build production-ready apps. CameraX is another Jetpack support library, which let you control the camera easier. As compose is still under development, lots of the views are still not available the compose way.

By ProAndroidDev -
Android News
Getting… your BottomSheetScaffold working on Jetpack Compose Beta 03
Getting… your BottomSheetScaffold working on Jetpack Compose Beta 03

By Carlos Mota

It’s Monday, no releases this week, and… there’s a new version of Jetpack Compose — beta 03—available. What a perfect time to just increment 02 to 03 and see what’s new. The API is (almost) final so after updating from alpha to beta there weren’t any big changes to do. However, and remember that’s still in development, there’s always something that I need to update. 

By ProAndroidDev -
Android News
Noisy Code With Kotlin Scopes
Noisy Code With Kotlin Scopes

By Chetan Gupta

Scopes make your code more readable? think again... You are going to encounter these scope functions namely let, run, apply, also, within every Kotlin codebase, along with all the mischievous ways developers exploit their usage from the way they were intended for. Let see how popular opinion on those ends up just as a code noise.

By ProAndroidDev -
Android News
Improving Android DataBinding with Bindables library
Improving Android DataBinding with Bindables library

By Jaewoong Eum

DataBinding is one of the most important factors for MVVM architecture. The basic concept of DataBinding is to link the view and view model via observer patterns, properties, event callbacks, etc. Linking and automating communication between the view via the bound properties or something in the view model has a lot of benefits in the MVVM architecture concept.

By ProAndroidDev -
droidcon News

Tech Showcases,

Developer Resources &

Partners

/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/home-details/EmployerBrandingHeader
EmployerBrandingHeader
https://jobs.droidcon.com/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/jobs-droidcon/jobs.droidcon.com
jobs.droidcon.com

Latest Android Jobs

http://www.kotlinweekly.net/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/kotlin-weekly/Kotlin Weekly
Kotlin Weekly

Your weekly dose of Kotlin

https://proandroiddev.com/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/pad/ProAndroidDev
ProAndroidDev

Android Tech Blogs, Case Studies and Step-by-Step Coding

/detail?content-id=/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Zalando/Zalando
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Zalando/Zalando
Zalando

Meet one of Berlin's top employers

/detail?content-id=/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Academy for App Success/Academy for App Success
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Academy for App Success/Academy for App Success
Academy for App Success

Google Play resources tailored for the global droidcon community

Follow us

Team droidcon

Get in touch with us

Write us an Email

 

 

Quicklinks

> Code of Conduct

> Terms and Conditions

> How to hold a conference

> FAQs

> Imprint

Droidcon is a registered trademark of Mobile Seasons GmbH Copyright © 2020. All rights reserved.

powered by Breakpoint One