DEV Community

alaje
alaje

Posted on • Updated on

Jetpack Compose Tidbits: The first dance with JC - Learning the steps

A dancing female image by Gordon Johnson

Image by Gordon Johnson from Pixabay


With Android's fresh way of developing UI, there's little to no XML which was formerly the primary way of designing UI for Android apps. With Jetpack Compose, you just declare what you need for creating your UI by calling functions and Jetpack Compose handles the implementation. When you need your UI to reflect come changes with the user's data, the functions you created just get called again with the new data.
Jetpack Compose comes with Android Jetpack, a collection of software components launched in 2018 that work to make developing Android apps easier and more efficient. Before JC, using views was the primary way of creating UI in Android, thus, many of the apps already existing are built with views, that is why Compose can exist in harmony with views so you can be sure that you don't need to throw away all your old code with views when starting out with Compose. Instead, you can make the shift to Compose in a way that suits you best.

If you've ever programmed with Flutter, chances are, you're going to fit right in with Jetpack Compose since Compose comes with a reactive style of programming.


Setting up the dance floor

To get started with Compose you must have Android Studio Arctic Fox.
After downloading Android Studio and successfully launching it, we can create a new compose project by clicking New Project,
Android studio click new project

And then click Empty Compose Activity to start creating your Compose app,
Android Studio select empty compose activity

A pop-up titled "Empty Compose Activity" appears, and we can go ahead to change our project's name to something more fitting:
create compose activity

The save location is where your project will locally be stored on your machine, and the package name uniquely identifies your app. The value supplied for the save location will be slightly different depending on your choices when installing Android Studio, and although you can change it and the package name, it would be better to leave it as is since the explanation given from this point is done in accordance with these exact values.

create a  compose project

The process is smooth and free of hitches if your internet connection is enabled and stable.
If you were unable to follow along with the above steps, you can visit Android developer's official site to see more info about the setup process.

Getting to know your partner, JC

After Android Studio finishes setting up your project, you should have a file with the name MainActivity.kt automatically shown in the editor window (the space available in Android Studio where the details of files are seen and interacted with).
You should also be able to see this sample bit of code:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            FirstComposeAppTheme {
                // A surface container using the 'background' color from the theme
                Surface(color = MaterialTheme.colors.background) {
                    Greeting("Android")
                }
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

code snippet: 1.0

This file belongs to the launching activity of your app called MainActivity. The class name also points to this. An activity, is the primary component of any android app that involves continuous interaction with the user. It serves as the entry point of your app in which you can let the user interact with your app. It, most commonly, shows UI as a single screen in the app. A more in-depth explanation can be found in the Android docs. MainActivity is your launching activity because it was automatically set as so in the AndroidManifest.xml upon the creation of your project. AndroidManifest.xml is a manifest file. It describes your app to Android systems, therefore, every app project you create must have it. To see what the manifest file looks like, go into the project window and double-click the manifests directory:
android project window

This opens up the manifest file in the editor window:
manifest file android
The highlighted part focuses on MainActivity. For an activity to be visible to the Android system, it must be declared in the manifest file using the <activity> tag. And this piece of XML

<intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
Enter fullscreen mode Exit fullscreen mode

makes it the activity that the will be launched from the launcher screen.


Back to this piece of code:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            FirstComposeAppTheme {
                // A surface container using the 'background' color from the theme
                Surface(color = MaterialTheme.colors.background) {
                    Greeting("Android")
                }
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

If you've worked with views, the code should be slightly familiar. In here, our first visible step into compose starts from setContent which has a content parameter that takes in a composable function that returns Unit as its argument. This content value becomes the root view of the given activity.
Take a look at setContent's definition:

public fun ComponentActivity.setContent(
    ...
    content: @Composable () -> Unit
) {
    ...
}
Enter fullscreen mode Exit fullscreen mode

Before moving ahead, let's slide into what a composable function is.


A Jetpack Compose app will primarily be made up of composable functions which serve as the building blocks of your app’s UI. You’ll create your UI With composable functions or composables for short. A composable function looks like any other normal function you can find in your code, except now it's marked with an
annotation @Composable. This annotation serves as a tag on your function that tells Compose that it is specially made for producing UI. Let's look at a very basic composable function:


@Composable
fun Greeting(name: String) {
    Text(text = "Hello $name!")
}
Enter fullscreen mode Exit fullscreen mode

We can see the annotation @Composable, and as previously pointed out, this makes Greeting a composable function. Let's notice how we started our function name with a capital letter following a PascalCase format. Anytime your composable function returns Unit, you are advised to use PascalCase in writing its name, and also to use a noun as the name. Focusing on the function we are calling next, Text(...), is a composable function that comes by default with Jetpack Compose. It prints the String value that was passed as an argument to its parameter "text" on-screen.
We've passed in a string template that references the parameter name, thus, whatever value will be called with Greeting will be what gets shown on-screen.
The Text function’s declaration looks like this:

@Composable
fun Text(
    text: String,
    ...
) {
    ...
}
Enter fullscreen mode Exit fullscreen mode

If you’ve ever used views to create apps, this is similar to TextView.


Now that we know what composable functions are, let's waltz back into analyzing the piece of code in our MainActivity.onCreate method.


From here, our next step comes with FirstComposeAppTheme which provides our app's theme. We can use a theme to style our app by providing a pool of colors, typography, and shapes that we can use to not only fuse our brand into the app but also grant it a uniform look and feel that looks aesthetically pleasing and is also coherent. Jetpack Compose provides MaterialTheme as the default theming system, but for more control over our app's look an feel, we can choose to build something of our own from scratch.
In our case FirstComposeAppTheme, automatically created upon the creation of own new project, sits atop MaterialTheme.
See the definition of FirstComposeAppTheme :

@Composable
fun FirstComposeAppTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable() () -> Unit) {
    val colors = if (darkTheme) {
        DarkColorPalette 
    } else {
        LightColorPalette
    }

    MaterialTheme(
        colors = colors,
        typography = Typography,
        shapes = Shapes,
        content = content
    )
}
Enter fullscreen mode Exit fullscreen mode

Let's focus on the part about MaterialTheme, where clearly, our FirstComposeAppTheme just wraps around MaterialTheme.
Now back to our code in our activity's onCreate function, we can see that setContent is a high-order function, so is FirstComposeAppTheme and Surface since they take in functions as parameters. Notice the FirstComposeAppTheme was passed as an argument to the content parameter, using the trailing lambda syntax. Composable, Greeting, is called in the lambda passed into Surface with the parameter "Android". Since we have “Hello $name” already set, this should later show "Hello Android" on-screen once it is run.
The comment above the invocation of Surface,

// A surface container using the 'background' color from the theme
                Surface(color = ...
Enter fullscreen mode Exit fullscreen mode

tells us that we are creating a surface container and passing in the background color set in our theme.
This surface container is a Material surface, meaning that it follows Material Design language where it serves as a depiction of physical surfaces having attributes like color, elevation, opacity and shape. See it’s definition:
@Composable
fun Surface(
modifier: Modifier = Modifier,
shape: Shape = RectangleShape,
color: Color = MaterialTheme.colors.surface,
contentColor: Color = contentColorFor(color),
border: BorderStroke? = null,
elevation: Dp = 0.dp,
content: @Composable () -> Unit
) {

}

You might have noticed by now how a composable is passed into another composable as its content's argument.

Treading down our MainActivity file allows us to see the declaration of Greeting. Below it we can see another composable function DefaultPreview which takes no parameter but instead has an extra annotation Preview. The Android Studio you installed comes with a preview window that allows you to view the UI built by a composable. This Preview annotation marks a function that contains no parameter to allow its UI be shown in the Android Studio preview.

@Preview(showBackground = true)
@Composable fun DefaultPreview() {
    FirstComposeAppTheme {
        Greeting("Android")
    }
}
Enter fullscreen mode Exit fullscreen mode

default preview android studio

In the DefaultPreview function, FirstComposeAppTheme function is called and the same thing done in the onCreate function of the MainActivity is repeated. We can pass in several arguments to Preview that control how the UI created by the composable functions we call will look like in the preview window. For example, we can supply showSystemUi = true.

@Preview(showBackground = true, showSystemUi = true )
Enter fullscreen mode Exit fullscreen mode

At the moment, we are only tweaking the values of showBackground and showSystemUi, to see more info about the annotation, place you mouse icon over the annotation text and wait for a pop-up to appear showing the documentation details of Preview. If nothing appears, place your input cursor in the midst of its characters, go up to toolbar area, click View > Quick Documentation. You should probably take note of the shortcut for this action.


The preview window should be open by default,
android studio default preview
but if it isn't, you can split the window.

android studio default preview

Using the preview window, you can always create composables and then see how they look before deploying to your device.


Now that we've taken our first steps with compose, let's actually start dancing in my next post.

Main Sources:
Android source code

Discussion (1)

Collapse
maxakash13 profile image
Akash Bhattacharya

great explanation