5

Bye XML, it was nice knowing you (pt. 1)

 3 years ago
source link: https://medium.com/mateedevs/bye-xml-it-was-nice-knowing-you-pt-1-50b195bab1a9
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Bye XML, it was nice knowing you (pt. 1)

This article will focus on the basics of Compose and example of implementation of specific UI design (just looks — no state management nor architecture).
Not everything is explicitly defined for a reason. You should follow along with your own code and not just copy mine :)
If you really don’t want to code along or are just stuck,
here is the full project.
Part 2
here and part 3 here.

I’ve always struggled a bit when implementing a complex UI hierarchy with XML. Not really because it’s slow or hard to make, but because it feels like a black box that you need to fight again and again to make it behave just the way you want it to. Of course, it’s not really a black box because you can inspect the code and see exactly what is happening, but you’re not really encouraged to with components like TextView.java having 13 705 lines of code and the elephant in the room View.java with 30 407 lines of code (at the time of writing).

View.java
View.java — Android source code

Another problem is that it’s impossible to do everything from the XML and still have to manage it from the Kotlin or Java code. So we end up jumping from XML to Kotlin, not really knowing how the UI will end up behaving. And in the end, the XML is only the initial state of the UI, and we have to manage every change. Data binding can partly fix this but mixing XML and Java code in one file only makes it worse, in my opinion.

I am not saying anything groundbreaking here. Every Android developer knows this and especially the Android developers who made the framework. That’s why they came up with something better. A modern UI toolkit that solves all of the old one's problems while (and more importantly) not introducing that many more.

It’s really that simple

I have some experience with declarative UI frameworks (e.g., React JS). When I heard about Jetpack Compose, I thought that if it’s at least the same experience, I’ll be happy but Compose really surprised me, Compose delivered life improvements in spades.
I love the trend where Kotlin frameworks try to simplify complex systems to be just as easy to write as regular code. Kotlin Coroutines broke the stigma that writing concurrent code is hard, and now Jetpack Compose is doing the same with UI. And it’s not just Android UI! The JetBrains team is making Compose Desktop, and there was even a working prototype of Compose for the web.

OK, but enough introductions. Let’s see really how easy it is to write UI with Compose with obligatory “Hello World” example:

// Activity::onCreate
setContent
{
Text("Hello World!")
}

And that’s it! No layout inflating, no XML file, and no need for instantiating 30k LOC long classes.
But it does not get that much more complex. Let’s turn it into a list of items:

Column {
repeat(100) {
Text("Item $it")
}
}

You don’t need adapters, and you don’t need to set any LayoutManagers and handle state change. All you need to do is to declare what you want, and Compose will handle the rest. If state changes, Compose runtime will refresh the UI by re-invoking our functions.
If we wanted the list to be lazy evaluated (equivalent to RecyclerView), we would just swap the Column for LazyColumn and repeat(100) for items(100) and that’s it.

The basics
Let’s go over the basics of what is Composable component and how to make one.

@Composable
fun MyComponent(name: String) {}

This is a declaration of a regular Kotlin function with @Composable annotation. The annotation marks the function for Compose compiler plugin, and we don’t really need to know the details of what it does under the hood. “It will sprinkle some magic onto it” will suffice. What is important to know is that Composable functions can only be called from other Composable functions (so it’s the same as suspend functions in that regard), and the @Composable annotation enables the function to remember the previous invocation (the keyword being remember so keep on that one, you will need it later)

If you want to know more about how the compiler works and how it transforms Composable functions, I highly recommend this video by Leland Richardson from KotlinConf 2019

Another important thing to mention before we put our hands on Compose is that Composable functions should be pure. That basically means that for each input (parameters of the function), there should be only one result, or in other words, if I call the same function with the same parameters multiple times, the resulting UI should be identical. This needs to be true because the Compose runtime can call our functions whenever it “feels” like (this is called recomposition), and we can never depend on some given “call behavior”.

Learn by example

OK, let’s dive into the code…finally :)
The best way to learn things is to try them out, so let’s take proper UI design and implement it using Jetpack Compose. I’ve chosen this design on Dribble because it has most of the things you need in a basic app screen: text, button, list, images, and some custom component (bell with notification dot).

1*NcmCAoDO631OT0LujAe72g.png?q=20
bye-xml-it-was-nice-knowing-you-pt-1-50b195bab1a9
Design by Aris Rahmat Fatoni

Divide and conquer
One of the first things you should do is to divide the design into components and each component into smaller components, and so on…
I’ve decided on 4 main pieces:
1. Header
2. Search
3. HouseList
4. PopularHouse
but you can structure it differently (or not at all, but I would advise against that)

Disclaimer:
I am only starting with Compose myself and have only ~100 hours of experience. If I say something inaccurate, be sure to let me know :)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK