CODEX

Exploring Jetpack Compose — Build a Simple Countdown Timer App

Inuwa Ibrahim
Geek Culture
Published in
5 min readMar 8, 2021

--

Recently the Android Team announced the release of Jetpack Compose beta—

“Android’s modern toolkit for building native UI. It simplifies and accelerates UI development on Android. Quickly bring your app to life with less code, powerful tools, and intuitive Kotlin APIs.”

Basically, Jetpack Compose uses a “Declarative” approach to build UI by providing Declarative API’s.

In simple terms - with Jetpack Compose, there will be no need for creating “XML” layouts to build your UI.

I will show you how to get started with JetPack Compose by building a simple Countdown Timer App, that countdown from 60 seconds (1 hr) to 0.

The final app will look like this:

Here is a video showing how it works

Okay lets start “COMPOSING” 🎼

STEPS

  1. Set up Android Studio
  2. Add Dependencies
  3. Create Activities, Classes, Files

1. SET UP ANDROID STUDIO

  • At the time of writing this post, Jetpack Compose is currently in beta, and all features are not fully stable. It is recommended to download Latest Release of Android Studio Canary to use with Jetpack Compose. Download here — https://developer.android.com/studio/preview
  • Install
  • After Installing, Create A New Project, In the Select a Project Template window, select Empty Compose Activity and click Next.
  • In the Configure your project window, do the following:
  • Set the Name, Package name, and Save location as you normally would.
  • Note that, in the Language dropdown menu, Kotlin is the only available option because Jetpack Compose works only with classes written in Kotlin.
  • In the Minimum API level dropdown menu, select API level 21 or higher.
  • Click Finish
  • Create 5 new Packages under project package name:
    Name them: helper, ui (Most times this is automatically created for you), utils, view, viewmodel

2. ADD DEPENDENCIES

  • Go to Build.gradle (Module:App)
  • Include the following dependencies along with the ones that came by default
//life cycle 
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.0'

//runtime liveDate
implementation "androidx.compose.runtime:runtime-livedata:$compose_version"

//viewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-
//view binding - added if you prefer to use viewBinding with compose
implementation "androidx.compose.ui:ui-viewbinding:$compose_version"compose:1.0.0-alpha02"
//konfetti
implementation 'nl.dionsegijn:konfetti:1.2.6'
  • Your full Build.gradle (Module:App) dependency block should look like this:

3. CREATE ACTIVITIES, CLASSES AND FILES

Helper and Utility Classes

  • Under helper package, right click and select New Kotlin File/Class
  • Click and name the class — SingleLiveEvent
  • This class is a subclass of MutableLiveData with a single Observer Observing it at a time, hence it is aware of view’s lifecycle, and emits data once when required
  • Full code below
  • Great, Under utils package, Create A new Kotlin — Object, name it Utililty
  • The Utility Object contains:
    - Time Constant — Which is 1 hr converted to milliseconds — 60000L
    - Function for formatting time, converting value to minutes and seconds which is displayed in UI.
  • Full code below:

ViewModel Class

  • Under viewmodel package, create a new class called MainViewModel
  • The MainViewModel class extends viewModel, it contains codes designed to store and manage UI-related data in a lifecycle conscious way. The ViewModel class allows data to survive configuration changes such as screen rotations.
  • It also contains Logic such as:
    - Function for handling Countdown — Pause, Stop, Start
    - Saving state of values of progress, time etc
  • Full Code for MainViewModel below:

View — Components and Activity

Components

  • Under view package, create a sub package called components
  • The components package lies all UI related views such as count down indicator, button and confetti view after countdown finishes
  • Right click components package and create a new kotlin file, name it CountDownIndicator
  • This file contains the UI for the:
    - Circular Progress Bar Indicator
    - Circular Progress Bar Background
  • Full code for CountDownIndicator below:
  • Under the components package again, create a new file called — CountDownButton
  • This view contains UI code for the button displayed on the app — With a text reading “Start” or “Stop” depending on the state of the timer
  • Full code for CountDownButton below
  • Lastly, under components package, create a new file called — ShowCelebrationView
  • This view simply contains “confetti” shown when the count down elapses. This was achieved with the help of an external Library — https://github.com/DanielMartinus/Konfetti
  • Full code for ShowCelebrationView
  • Notice how we use AndroidView() to reference of traditional custom android Views/UI. This is useful Compose interoperability. You could also use AndroidViewBinding() for binding xml layouts while using in a composable.
    More — https://developer.android.com/jetpack/compose/interop
  • Now, under view package, create a new file called — CountDownScreen
  • This file groups all the components we just created to a single file as a composable, so we can finally use it in our activity.
  • Full code for CountDownScreen below
  • Note just like coroutines, a composable function can only be called within a composable function, that is why we were able to call those functions inside this class which is annotated with @Composable

Activity

  • Now open your MainActivity.kt file and add these after super.OnCreate
setContent {
MyTheme {
TransparentStatusBar(windows = window)
MyApp()
}
}
  • MyApp is a composable function that calls the CountDownScreen composable function which displays UI related Items
  • Full Code For MainActivity below:

AND WE ARE DONE! 👏

Can you believe we just built an android app without any XML layout.

This project was built as part of an entry for #AndroidDevChallenge week 2 for jetPack Compose.

Full Code

https://github.com/ibrajix/TimerJetpackCompose

Learning Resources:

My take on JetPack Compose

PROS

  • Easy to build layouts which can be extremely flexible and reusable
  • Maintainable code — Easier to test — Components Based UI.
  • Less lines of codes
  • No need for Adapters for recyclerView
  • Easier to create animations and complex shapes when compared to traditional XML.

CONS

  • Unstable Preview Layout which just doesn't work most of the time
  • Limited resources to learn, — When stuck, its so hard to find a solution quickly
  • Changes to inbuilt API’S e.g getting a context in a composable was:
    val context = ContextAmbient.current,
    its now:
    val context = LocalContext.current.
    Also RoundedCornerShape() class now requires top, bottom, (start/end) values as parameters which was not so before. Something like — shape = RoundedCornerShape(25.dp), throws an error — “ Type mismatch. Required: CornerSize Found:Dp”

See — https://stackoverflow.com/questions/66496662/jetpack-compose-has-cutcornershape-api-now-changed/66496849#comment117588166_66496849

VERDICT

Jetpack Compose is great and most of the cons I listed will surely be worked on/improved when it is on stable release.
Obviously, not ready for “production apps” (For me!)

Thanks for reading! 🙌

Reach Me

https://linktr.ee/Ibrajix

--

--