Why Jetpack Compose? by Miriana Itani

Automatic Summary

Discovering Jetpack Compose: Google’s New UI Toolkit for Android Developers

Today, we're delving into the innovative world of Jetpack Compose, Google's modern toolkit for building native UI. Released a few years ago and now available in a stable version, Jetpack Compose is being actively recommended by Google for all Android native developers.

What is Jetpack Compose?

Google's Jetpack Compose simplifies and accelerates UI development by bringing the application to life with less code, powerful tools, and intuitive Kotlin APIs. It builds the UI in a more efficient, object-oriented manner, which promotes code reuse and saves memory, making it an exceptional tool for developers.

How Does Jetpack Compose Work?

Jetpack Compose works by observing changes to the state, similar to MVVM (Model-View-ViewModel) architecture. Whenever a change occurs in the state, the UI, in response, modifies based on the change. Consequently, an event dispatches an updated state, leading to a display change in the UI.

This flexible response to state changes also aids in saving memory, as unlike traditional UI models that redraw the entire layout upon every minor change, Jetpack Compose only changes the specific components affected by the state change. You can see this advantage during our live coding sessions where we demonstrate how Jetpack Compose aids in efficient memory management.

Demonstrating Jetpack Compose with a Live Coding Session

In the live coding session, we showcase how to create a composable activity, display previews of UI components without running the application, and simulate the addition of new components.
During the demonstration, we also cover a critical aspect of Jetpack Compose: understanding and managing states, mutable states, and the "remember" function.

Why 'remember' State in Jetpack Compose?

'Remember' in Jetpack Compose helps keep track of changes in the state; it stores the state in the composition and keeps it across recompositions. Although 'remember' does not cater to configuration changes, Compose offers functions that retain state across these changes.

When coupled with mutable state, 'remember' allows Compose to retain the previous state and respond to new ones, thereby only redrawing affected components and not the entire UI — this showcases a massive advantage in memory management.

Choosing Between MVVM and MVI Architectures with Jetpack Compose

Interestingly, apart from traditional MVVM architecture, developers can also integrate Jetpack Compose with MVI (Model-View-Intent) — a newer architectural pattern where the ‘intent’ is not a typical.Android intent, but signifies the intention of an action.

However, personally, I found that while MVI accommodates separate classes for different intents, leading to multiple classes for a single application, MVVM provides a cleaner, more maintainable approach to Jetpack Compose, especially considering its ease in unit testing scenarios.

Getting Started with Jetpack Compose

To start with Jetpack Compose, add its dependencies in build.gradle file which include – Compose UI, Material, and Tooling. This set-up allows you to benefit from Compose's structuring, theming, and preview features.

In closing, I would recommend developers explore other concepts around Jetpack Compose, such as the state hoisting, which entails separating the state holding composable function from the UI, thereby making it easier to test and maintain.

And that's our wrap on the exploration of Jetpack Compose, its workings, live demonstration, and thoughts on optimal architecture patterns. Feel free to reach out if you have any questions or if you'd like to dive deeper into Jetpack Compose!


Video Transcription

So today we are going to be talking about Jetpack compose. So if you haven't heard about Jetpack compose before, it is um the new way of doing U I developed by Google. So Google has developed Jetpack compose a couple of years ago.It was in bed and and it was fully released as a stable version. And Google is recommending all Android native developers to move into Jetpack compose. Why should we use Jetpack Compose? So Jetpack compose simplifies and accelerates the U I brings the application to life with less codes, powerful tools and initiative cotton API S and as we all know also uh or if you have, if you aren't familiar with this, um Also Google moved Android from Java to co and it still supports Java.

But at the moment, it is more recommended to use uh Cola uh because it's the new language. So also Jetpack compose builds um the U I in a way of like objects. So they're like, let's assume we have, for example, a loader and this loader is a custom loader like uh Lotte, for example. And this loader is gonna be visible in every single page of the application rather than having this loader be included in every single page or having to build it dynamically in a base activity. We build the loader as a class using UI and we just call the composable widget. This simplifies libraries reusability of codes in UI and it also saves memory which we're going to see in a few, we're gonna do a live coding session. We're gonna see how Jetpack compose actually helps us in saving memory. Sorry, how does compose work compose works? Usually by observing states, if you guys are familiar with MV PM, we used to observe live data. This is the architecture that also Google implemented a few years ago and it's now recommended to be used.

So MV PM is when uh when we put save a variable inside the view model and the view communicates with the view model and the view model communicates with the repository, the model, the data. So that's the word of MVV. So similar to that concept, this is how Jetpack compose works. So the composer observes the changes to the state and it it modifies the UI based on the change of the state based on the event. So the event is going to dispatch the update state and the update state is going to change the display in the UI. OK. So now we are going to move to a live coding session. OK? Just let me see how to share my screen over there. Me suck. OK. There we go. OK. I'm also gonna, so this is your, this is the composable layout as we could see there is main activity. 000, sorry. First, if you wanna create a composable activity, just go into new uh compose new empty composed activity. Mm That's it. Or if you wanna create a new project can go new, new project, empty Composed activity and you're gonna be seeing something like this without the commented code that I have already on my screen. Ok? So now we're gonna have like this is the greeting it's android but as we could see here, it's hello testing. So why is it hello testing? Because I'm using the preview.

The default preview is just uh a way that Google gave us rather than every time running the application, we just have a sample display of what we're going to see on the application over here. So I have the word testing. If I change it into trust, for example, it's gonna automatically change over here in the test. This is the default preview but if I run my application, I try to just give me a second. Mhm. Ok. Yeah, I'm not sure. Um you guys can see my screen. Ok. Just give me a second to show you my screen. Ok. So now you're able to see her low android. The reason we're seeing her low Android rather than test is because when we are calling the function inside the jetpack compose. We are calling it greeting and we're giving it Android. Uh Let me try to, ok, so far so good. Now I'm going to split only to the code base and we are going to implement a simple counter just to display how the states work using jetpack compose. I already have those codes pre coded just to save time. Maybe we could go into MV I after we're done with this if we have time. So I'm going to comment this default code and and comment this. So what I did over here is just call a water counter, which is a composable function. Ideally, this function should be present in a file composable on its own. So that for reasons reason and for this page to be more readable and we're just going to run it.

So we're supposed to see on the screen just um a text that's going to display, you've had zero glasses. That's exactly what we're gonna be seeing. And also it's, I wanna point out that here in the default preview. We are still seeing hello test because over here I did not change it. Ok? Now let me share again my screen. Sorry, we're gonna have to keep bumping from the cold to the emulator. OK? So it's, you've had zero glasses, that's basically it. So if you go back to the code, OK, we are going now to implement a counter plus counter. That's it. So over here, we have part count equals to zero. We're just displaying the text and we have a button. The on click function is count plus plus, simple enough. OK? So that's all that we are doing over here. And this should not be any problem and I'm going to run it. OK? OK. So now I'm gonna be clicking the add one. So I'm actually clicking it as you can see on the screen, but nothing is changing. And I'm going to paste the code over here that we just wrote, going to paste it. And I'm going to tell you exactly what is wrong over here. So what we did is we actually had a bar count equal to zero and we're having count plus plus. But the problem with this is that every time I am clicking on the button and the count plus plus, it is actually reinitialize bar count equals to zero.

So technically speaking, the state is never changing, it's always zero. So now we're gonna see how we are going to solve this or attempt to solve it since we said we're gonna be working with states and we said that states resemble uh live data MVVM. So we're gonna be working with the mutable states because they're gonna be changing essentially everything that's a mutable state is any variable in the code that is going to change over any point in time. Think of it as a display of loader, display, loading, success error. So this is a change state that has to change over time. So that's initially, I'm just going to import those and I'm going to run the app again and I'm going to paste the code over here. I just added remem uh just added the mutable state of the integer. That's all I did. And now I'm running the code again and as we can see nothing is changed. Now I'm going to click on the button and still there is no zeros. The the there the country is not changing because having the state as a mutable does not actually have composed disposed the event, it's just tracking it, it's not remembering its state. So what we need to do is add, remember. So I'm gonna show you what I did. Just give me a minute. So this is exactly what I did and I'm going to input it because it's a function done already by compost. OK.

So usually remember and immutable states, technically speaking, they're always bundled together so that the compose always remembers the previous state so that it can uh dispose an event of uh the newer state. So they're technically speaking, always together and now we're gonna rerun the application and now I promise you it's going to work. Should work. Mhm. Mhm. And as you can see, OK, I said this should work but it did not work, just give me a second. It did not run well. OK. And now as we can see, uh you can, you can see that it's working. Just give me a ok. Here it is. Now, as you can see the counter is working correctly. Now, I wanna mention over here that the remember uh I'm going to post the code also. So the last code that I'm gonna be posting is the correct way of doing the mutable sticks. So the remember over here uh is not going to work if we have uh configuration changes. So if we, if I turn the, if I auto rotate my phone, it is going to automatically come back to zero, there is a function in compose that's gonna save the state uh throughout the configuration changes, but we're not gonna go through it, but I thought I should mention it.

OK? So technically speaking, this is the beauty of state and compost. So what's happening over here? So in this function, it composes remembering the state of the initial value and is changing it when there is a need to change. And the beauty of this is that well, now we only have one function. But imagine if we have um a button, a list counter and a few other things so compose at the moment is only gonna re uh de display the text. It's gonna change the U I only of the text, which is a huge memory consumption rather than redoing the whole U I over and over again. It's just this it's just changing the value of the text and this is helping us a lot. And if we have the water counter in a different screen, we would be able to call this from anywhere inside the application by simply just adding it over here. And I wanted to note something that in compose. Um Here, I'm using a column because I want the values uh the UIs displayed uh vertically. However, if I wanted them to be displayed horizontally, I would use a room and if I wanted them both horizontally and vertically, something like a constraint layout, I should be using uh a box. So, so far concerning what we've covered for the time being.

Does anybody have any questions? Oh, I'm sorry, I didn't realize my cat was behind me. OK. OK. I guess we can move on to something that's a bit bit more architectural. OK. So for the next part of our session, I'm going to talk briefly about compose with um oh no, this is the native Android uh cot not javascript, no worries. Uh So for the next part of our session, we are going to be talking briefly about the new architectures that are booming nowadays. So we have just back composed with MVVM, which is the initial uh uh architecture that is recommended by Google and there is a new architecture that developers are currently working with and it's called MV I. So MV, I is based on modern view, intent and the intent is not the normal intent that we use in and studio. It's not the, uh it's not going from one activity to another. No, that's not it. The intent is actually the intent of an action. For example, the intent of clicking a button like we have here in the counter, the intent of showing a loader and et cetera. So it's like intentions if you want, if you want to say.

So what happens here in the model view, intent is actually the intent and the view are coupled in a way or another together and any change in the intent would lead to a change in the view and this happens by the state. So the state, whenever it's changing is gonna change the intent and the view would be observing the intent and the intent would automatically change uh personally speaking. And this is just a personal opinion. I've tried the Model view intent and I've tried the MVVM with Jetpack compose and I highly recommend Jetpack Compose for a couple of reasons. One of them is the model view intent contains so many classes. If you want, I could show you a code with, you know, I'm gonna show you one code with the model view intent. Just give me a minute to run the application. OK? So this is actually a code that's written using MV I, it's just a simple loader and I'm just showing a loader based on changes. So this is just back composed, that's showing a lot of animation code film, maximum width and maximum height. I'm giving it a background color, nothing uh very fancy over here happening. So this is the base composed view model because as I said, intent kind of use M PM but and it observes intent rather than observing states.

And we are using uh flows if you're familiar with them and we're using channels. So we're sending the intents to channels. OK. Just let me see. Where are we? OK over here. So our splash view model because uh what I'm doing over here is that I'm showing in the splash activity. I'm showing the splash screen, which is a display of the loader actually. So this is the composable splash screen. And I'm telling it that if the intent of the splash view state was a loading display, a loader else just display an image, that's it. And I'm changing the intent manually over here. So here, I'm just telling it what is the state of it? I'm telling it it's state. So we have three states which is anti loading. And so loading is just going to display the loader. Other than that, it's just going to display an image. But we have all of those classes over here just so that we could do a simple loader. So every single intent is gonna require at least two or three classes. So if we have a huge application that's going to, let's say, work with 1010 buttons, we're gonna at least have around 30 classes. So this is my personal opinion on mvimvvm is easier to write cleaner code.

Like you could see, you're technically even not really doing MVVM because you are observing the state using live data rather than observing the live data itself. But it's still way cleaner easier to test. And for those of you who are crazy about unit testing or who do unit testing, which is by the way, very highly recommended and everybody should be doing it. Um It's also better to use MVVM with Jetpack compose rather than using MV with jetpack compost. So for up till now, does anybody have any question about the architecture? Like my personal opinion about an architecture? Like why are we using MVVM with Jetpack compose rather than MV I with Jetpack compose? OK. I think everything is perfectly clear. Then let me reopen the application and we could talk a bit about the library, the themes in jet back compose everything that's actually completely new in this part. So now here over here we have the U IC. So before if you're familiar with Android or if you remember we had this rest folder, the values and everything actually was here. But now we get back on pa everything is in classes, the themes, the type, the type, which is the font actually uh color. Everything here is in separate classes and it's in a package, this is also easier to maintain rather than having a completely separate package. So this is also one of the things that are considered a huge change in jetpack compose to add jetpack compose to our application.

And as I said, it is a stable version and you should, people should be taking advantage of the coupling delicates inside jetpack compose. So we are having decompose U I decomposed material and the tooling preview, which is needed to just preview whatever we are previewing over here in this part so that we don't, so that we do not test, we do not run the application every time we need to display something over here.

So even over here, as I said, it's showing greeting because that is what I sh told it to show I refresh it. It's gonna take a while to refresh. Yeah. But yeah, of course, you need a very powerful laptop to work with the composer. Well, to work with Android studio to begin with, not only compose OK. OK. So it's rendering the view and here it is, I'm just going to minimize it. So this is our typical default preview. So I do not need to run the application to see the preview of this and this actually helps a lot. So this is why we have that default preview life cycle. It's because we are working well. We should be working with MVVM regardless whether it's MV I or MVVM. We are working with the view model. So we need the life cycle because the view models are life cycle aware activity compose because we are extending a component activity which is the new activity that uses jetpack compose. You are in for the modifier, the padding the box, the column, everything. So this is for example, if I want to use a row instead and we can refresh hm and here we have it. Hm I'm just gonna take it back into column because it looks better this way. Ok. Ok. Now that we have that covered. Mhm.

Just let me check if there's anything that I want. Yeah, so I just wanna add about something about the remember that it is stored in the composition and kept that cross recomposes positions. OK. So this is something very important because as I said upon recomposes position, we need the remember state to remember the state and that is actually a wrap up of our sessions. I expected more questions honestly, but I am going to drop down my linkedin and please feel free to connect. And if you have any questions, anybody if you would like to continue discussing more Jetpack compose states, there's also something that's called state hosting. I could go into it, but I felt like it's an advanced topic. But for state hosting, we technically are just separating the views because if a composable is holding the remember state on its own along with everything else it becomes harder to test because they're coupled together.

So with state hosting, um what we actually do is we separate the composable function into two functions. One of them is just going to be holding the state and the other is going to be holding the rest of the UI which is the text and the button. And we are going to pass the value of the variable from the first composable function into the second composable function. And that's how we, that leads to state hoisting, which is a very important topic that I also advise you to read on. So I'm just going to drop it down over here state hoisting and just uh compose because it helps in testing and it helps to maintain uh a stateless uh composable quit and the state for and the, the composable widget that has a state, it's called a state full composable widget.

Ok. So anything else if anyone would like to add anything, feel free to drop it down right now, we still have like around uh 10 minutes for our session to end. So anything does anybody like to add anything right now? Ok. I guess uh we are done for today. Um I'm so happy that you were part of the session. And as I said, please feel free to con thank you. And as I said, feel free to connect on with me on linkedin and we could continue this in private. Have a Good day, everybody. Bye bye.