Battery Project Log 1 - Starting the project

I am building up my portfolio of projects to showcase my ability in building apps using the current "best practice" technologies. Instead of diving straight in to a massive project like rebuilding TikTok or even a "Calendar App", I am going to start with a small project. Keeping the app to a scope of a single screen will remove the need for things like navigation flows, complex state management, and other things that are not the focus of this project.

This first project focuses on building on Jetpack Compose. I'd like to get used to the composable framework and understand how to build a UI with it. Here I'll be building off my learning of the basic components, modifiers, and layouts. I'll be introducing basic state variables for components as well as basic animations.

Adding a Timer to the composable

Found this resource on how to add a timer to the composable: https://medium.com/@android-world/jetpack-compose-countdown-timer-9531dd3119a6

It was really helpful in getting me introduced to LaunchedEffect and how it can be used to run asynchronous code for a composable element.

However, I found there was no real way to handle updates to the timer. For example, if there was a battery update or the charge time goes slower, there is no way to update the timer.

The challenge here is because the timeLeft variable is now stored outside of the composable. Whenever we get a new chargeTimeRemaining value, it doesn't update the state.

@Composable
fun BatteryDisplay(percentAsInt: Int, chargeTimeRemaining: Long, columnAlignment: Alignment) {

    var timeLeft by remember { mutableLongStateOf(chargeTimeRemaining) }

    LaunchedEffect(key1 = timeLeft) {
        while (timeLeft > 0) {
            delay(1000)
            timeLeft -= 1000
        }
    }
}

I wonder if we can use two LaunchedEffect to solve this problem. One to track the time left and one to update the chargeTimeRemaining.

@Composable
fun BatteryDisplay(percentAsInt: Int, chargeTimeRemaining: Long, columnAlignment: Alignment) {

    var timeLeft by remember { mutableLongStateOf(chargeTimeRemaining) }

    LaunchedEffect(key1 = chargeTimeRemaining) {
        timeLeft = chargeTimeRemaining
    }

    LaunchedEffect(key1 = timeLeft) {
        while (timeLeft > 0) {
            delay(1000)
            timeLeft -= 1000
        }
    }
}

How to display time in a readable format

I learned that Kotlin has a really cool Duration class that can be used to represent time. Values can be converted into a time unit by extension functions to create durations (15.seconds)

These can be used to add and subtract durations:

215.seconds + 19.minutes

The cool part is that the natural toString() method prints it out in a really easy to read format 2m 45s

Import extension function