Bridging between Composable and View’s lifecycles
If you happen to include an Android background, you need to be aware of the notion of lifecycles. Jetpack Compose introduces a brand new paradigm to construct declarative UI utilizing Composables. They arrive with a simplified lifecycle together with three phases:
- The getting into part.
- The recomposition part.
- The exiting part.
The official documentation describes intimately how a Composable behaves throughout its full lifecycle.
Now, you could be tempted to suppose the Composable’s lifecycle replaces the View’s lifecycle. Despite the fact that the naming aligns, we’re speaking about two totally different notions.
As an example, even should you’d construct a pure Compose software, your Composables might have to work together with the View’s lifecycle. That might be the case should you’d have a Composable refreshing some knowledge when the applying comes within the foreground.
But, the Composable is aware of nothing in regards to the View’s lifecycle. You’ll have to bridge these two universes to carry this consciousness to your Composables.
Let’s assume we’re constructing a pure Compose software. Together with a display screen Composable
ProductsScreen. This display screen injects a ViewModel — by way of Hilt as an example — to fetch the merchandise. We’d have the next code:
The ViewModel launches a coroutine when created and delegates the fetching operation to a repository.
Now, we’d prefer to refresh our merchandise every time the person shows this display screen. This may occur when the person goes to the background and re-enters the foreground — offered the system didn’t kill the applying. Or should you’d navigate to a distinct display screen then navigate again to the
You’ll quickly notice our pattern code doesn’t fulfill our necessities. The fetching will solely be lively through the first time the Composable seems. That’s as a result of the ViewModel cancels the coroutine because the Composable exits the composition tree, however doesn’t relaunch it when re-entering the composition part.
One resolution could be to depend on the Composable’s getting into part to fetch your merchandise. You may expose the fetch methodology out of your ViewModel and name it out of your Composable. Bear in mind to name this methodology utilizing a facet impact. In any other case, you’ll fetch your merchandise not solely when the composable will get seen however at every recomposition when its state will change!
If you happen to’d prefer to name it as soon as when the Composable enters its composition part, you need to use a
Unit as a key — or
true, so long as it doesn’t change through the composition.
We haven’t checked all bins although. Utilizing the getting into part will assist us refresh our merchandise when navigating again to this display screen. That’s not the case when the person has put the applying within the background.
It issues to differentiate how Composable and View’s lifecycles work. However it’s additionally helpful to grasp you can mix them.
In a pure Compose software, you could create an Exercise as an entry level. We are able to depend on it to get the View’s lifecycle and cross it all the way down to our Composable.
However passing down some occasions from the holding Exercise to the Composable will get tedious. Particularly when you may have a number of dad and mom Composables in between. Fortuitously, we are able to instantly make any Composables lifecycle-aware.
If you happen to’re not aware of lifecycle-aware parts in Android, I’ve lined it with an identical use case in this article.
An analogous configuration works with Jetpack Compose. However there exists a better, extra “Compose-like” option to obtain it. Every Composable exposes the present lifecycle proprietor the place you possibly can retrieve the View’s lifecycle. Utilizing a
DisposableEffect side-effect, you possibly can retailer the View’s lifecycle state and react upon it whereas safely detaching its observer when the Composable exits the composition tree.
All of it will rapidly turn out to be boilerplate if extra Composables would flip lifecycle-aware. We are able to write a Composable extension methodology:
With this configuration, you possibly can react to the View’s lifecycle with a couple of further strains of code.
Within the previously linked article, I’ve talked about how very important ViewModel performs in your software scalability. Particularly when some enterprise logic is tightly certain to your View’s lifecycle.
Utilizing Compose doesn’t absolve you from doing so — despite the fact that it makes the separation of concern simpler.
With the above resolution, the View nonetheless holds the accountability of reacting to lifecycle occasions and requesting the fetch to the ViewModel. Ideally, the ViewModel ought to maintain it.
Utilizing the identical method, we create one other Composable extension methodology to let any
LifecycleOwner observe the View’s lifecycle. Then, we let the ViewModel implement the
DefaultLifecycleObserver interface. We are able to transfer all of the logic into the ViewModel!
We’ve seen that, with a easy use case, relying solely on the Composable’s lifecycle gained’t make the reduce. With the lifecycle-aware parts library and a
DisposableEffect, you possibly can switch the lifecycle occasions to the ViewModel.
Additionally, the testing course of stays unchanged in comparison with my earlier article. This implies we are able to preserve our lifecycle-aware ViewModel logic regardless if injected by a View or a Composable. Solely the lifecycle binding differs — and it’s much more easy with Compose with the extension methodology!
I hope this may show you how to in your migration course of in the direction of Jetpack Compose whereas mitigating the impression in your code. Completely happy coding!