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
Evolution of Android Update SystemEvolution of Android Update System
Evolution of Android Update SystemEvolution of Android Update System

By Ivan Kuten

So, how can you update Android on mobile devices? While developing software for Smart TVs and Android-based set-top boxes, we’ve narrowed it down to four ways, discarding some very exotic options:

By ProAndroidDev -
Android News
Happy Railway
Happy Railway

By Hadi Lashkari Ghouchani

This post is on the tail of Railway Oriented Programming in Kotlin by Antony Harfield. So you need to read it first and continue here. As it’s obvious I really liked it and tried it out. It needs every process have a result like

By ProAndroidDev -
Android News
Unit Tests and Concurrency
Unit Tests and Concurrency

By Stojan Anastasov

Once Retrofit added RxJava support, RxJava became my go-to concurrency framework for writing Android apps. One of the great things about RxJava is the excellent testing support. It includes TestObserver, TestScheduler, RxJavaPlugins so you can switch your schedulers in tests.

By ProAndroidDev -
Android News
When Compat libraries will not save you
When Compat libraries will not save you

By Danny Preussler

And why you should avoid using the “NewApi” suppression! The idea of “Compat” libraries was probably one of the key aspects of Android dominating the mobile space. Other than with iOS, Android users often could not update their operating system after a new version launch, simply as their phones won’t allow them to, the Android problem of fragmentation.

 

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