Jetpack Compose: Random number flow

Introduction

In Android development, Jetpack Compose has become the go-to framework for building user interfaces in a declarative way. One of the key features of Jetpack Compose is its integration with Kotlin coroutines and Flow, allowing developers to handle asynchronous data streams effectively within the UI. This article explores how to create a simple application using Jetpack Compose and Kotlin Flow to display a random number that updates periodically. We will walk through an example Kotlin code, breaking down its structure and explaining how different parts come together to form a functioning app.

This particular example focuses on using Kotlin’s Flow to emit random numbers at regular intervals, which are then displayed on the screen using Jetpack Compose. The combination of Compose’s state handling with the power of Flow provides a responsive and flexible way to handle dynamic data in your Android apps.

Code Breakdown

The MainActivity class extends ComponentActivity, which serves as the entry point of the application. In its onCreate method, the UI content is set using setContent, a function provided by Compose to define the composable hierarchy. Within setContent, the theme of the app is applied using ComposeStateTheme, ensuring consistent styling across the app. Inside the Scaffold, which is a common layout structure in Compose, a TopAppBar is defined, showing a simple title "Compose - Random Number Flow". The core content of the UI is then defined within the MainContent composable.

The MainContent function is where the random number generation logic resides. A Kotlin flow is used to emit random integers periodically. Flow is a powerful API in Kotlin for handling asynchronous streams of data. In this case, the randomNumberFlow emits a random integer after a delay of 1000 milliseconds (1 second). This delay simulates some background processing or asynchronous event, making the app dynamic and reactive.

Within MainContent, the emitted random number is collected using collectAsState. This extension function collects the flow and transforms it into a state that Compose can observe. The by keyword is used to delegate the randomNumber variable to the value collected from the flow. The initial state is set using Random.nextInt(), ensuring that the app starts with a random number before the flow begins emitting new values.

For the UI layout, the Box composable is used to center the text displaying the random number. The Box modifier fillMaxSize() ensures the box takes up the full screen, while contentAlignment = Alignment.Center centers its content. Inside the box, a Text composable displays the current random number. The TextStyle is set to use a font size of 40 sp, giving it prominence on the screen.

Summary

In this example, we’ve built a simple Android app using Jetpack Compose and Kotlin Flow to display a random number that updates every second. The combination of Compose's reactive UI model with Kotlin's Flow for managing asynchronous data streams provides a seamless experience. The collectAsState function bridges the gap between the flow and Compose’s UI state, ensuring that any changes in the data are reflected in the UI automatically.

This example demonstrates how easy it is to integrate Flow with Jetpack Compose, allowing developers to handle dynamic and asynchronous data effortlessly. Whether you’re fetching data from a remote API, listening to system events, or simulating random data, Jetpack Compose’s reactive nature makes building such features straightforward and efficient.


MainActivity.kt

package com.cfsuman.composestate

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.sp
import com.cfsuman.composestate.ui.theme.ComposeStateTheme
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.flow
import kotlin.random.Random


class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeStateTheme {
                Scaffold(
                    topBar = { TopAppBar(
                        title = { Text(text = "Compose - Random Number Flow")}
                    ) },
                    content = { MainContent() },
                    backgroundColor = Color(0xFFEDEAE0)
                )
            }
        }
    }
}


@Composable
fun MainContent() {
    val randomNumberFlow = flow<Int> {
        delay(1000)
        emit(Random.nextInt())
    }

    val randomNumber by randomNumberFlow
        .collectAsState(initial = Random.nextInt())

    Box(
        Modifier.fillMaxSize(),
        contentAlignment = Alignment.Center
    ) {
        Text(
            text = "$randomNumber",
            style = TextStyle(fontSize = 40.sp)
        )
    }
}
More android jetpack compose tutorials