It’s been a long time since I’ve wanted to write this article. Time to go at it, shall we? :)

People always seem to be surprised and say, “wait, you DON’T use Jetpack ViewModel, Jetpack Navigation, and Dagger-Hilt? Then what DO you use?”

This article intends to answer that. We use Simple-Stack.

(If you prefer watching talks, then a talk on the same subject is available at

What is Simple-Stack?

Simple-Stack is a navigation framework that I’ve been working on since the beginning of 2017, although its roots go back to 2015 — when we were still experimenting with multiple versions of…

Have you ever wanted to navigate between two Composables? Do you wish it were as easy as backstack.goTo(SomeScreen(arg1, arg2)) and you would go there?

Good news, because now that seems to be possible with Simple-Stack’s Compose integration — which I consider BETA for now, but nonetheless, it’s possible.

What it looks like

Initial setup and dependencies:

First, you would add the dependencies:

implementation 'com.github.Zhuinden:simple-stack:2.6.0'
implementation 'com.github.Zhuinden:simple-stack-extensions:2.2.0'
implementation 'com.github.Zhuinden:simple-stack-compose-integration:0.2.0'

And of course, you’d add Jitpack (not JCenter):

// build.gradle
allprojects {
repositories {
// ...
maven { url "" }
// ...

And most importantly, you’d enable Compose:

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8…

It’s been a recurring question, regardless of navigation framework of choice: how is it possible to create a screen with a bottom navigation view, that would host a navigation history stack per each tab?

Each framework has its own unique ways. For example, with Jetpack Navigation you might use the NavigationExtensions, which requires you to host the BottomNavigationView at the Activity-level.

But how would you do it with Jetpack Navigation, in such a way that the BottomNavigationView is confined to a single child fragment, and that child fragment would host all tabs that each have a NavController (backstack) available to…

I’ve been meaning to write this article in a while.

Hopefully, the following tips and style recommendations (in no particular order) will help you write better Kotlin!

Let’s get on with it, shall we?

For 2 or more constructor arguments, prefer not to keep the properties on the same line as the class name in the constructor definition

class MyClass(
val a: A,
val b: B,

): MyParentClass(a, b), MyInterface {
// ...

This format is preferable, because when adding the 3rd argument, important bits (such as a possible base class or interface) can appear too far on the right side of the screen.

Listing them one after the other (including the trailing comma since 1.4.21+) allows for better readability and extensibility (reducing…

Something people could ask me as they’re reading this title: “Hold on a second, isn’t Dagger-Android no longer in active development? Isn’t it made obsolete with the introduction of Hilt?”

Technically, yes. Dagger-Android is superseded by Hilt. So there is a good chance that if you are already using Hilt, then for the most common cases (injecting Activity, Fragment, ViewModel, Worker), you don’t need to think about Dagger-Android whatsoever.

However, as I still see @ContributesAndroidInjector popping up every now and then, I feel that it’s best if I write an article on how it works, what it intended to solve…

It’s been a recurring question, regardless of navigation framework of choice: how is it possible to create a screen with a bottom navigation view, that would host a navigation history stack per each tab?

Each framework has its own unique ways. For example, Jetpack Navigation provides NavigationExtensions as a sample, there’s FragNav, but how would you do it with Simple-Stack?

How bottom navigation with child fragments normally works

If you intend to create a BottomNavigationView that is hosted by a Fragment (and that Fragment hosts each tab as a child fragment), there’s a bit of work needed to be done. To keep the fragments alive while switching between…

Jetpack Lifecycle is quite powerful. We can extract logic, and make it lifecycle-aware. In fact, this allowed us in a previous article to simplify viewbinding and make it a single line.

However, I need to provide a quick heads-up: all is not as it seems.

The provided gists and code snippets assumed that the code in AutoClearedValue is always correct. In this article, I’ll show you how to break it.

The original source

The general idea behind AutoClearedValue is that a value hidden by this delegate would only be created when it is set (in our case, when it is accessed), and…

Top-level “domain” module is a code smell.

Merry Christmas to all!

The subject of this article is one that has been on my mind for a very long time. After all, “Clean Architecture” is often seen as the end goal, the hallmark of the finest of Android application code structure — it is the best of the very best. The name itself, “Clean Architecture”, signals that it’s a good thing ~ after all, who wants to work with “messy” code in comparison?

Of course, the title of this article shows that this isn’t the conclusion we’ll come to. …

You can also follow the related discussion thread on /r/android_devs.

LiveData is a misunderstood beast. Every so often, you see comments like “LiveData does not belong in Repositories”, or that with the existence of RxJava, Coroutine Channels, or Coroutine Flows — there’s “no reason to use LiveData at all”.

While there are components in these libraries that have overlapping responsibilities (BehaviorRelay, ConflatedBroadcastChannel, MutableStateFlow), that doesn’t mean LiveData is useless.

With the relatively new additions to Jetpack, such as the liveData { coroutine builder, LiveData is actually quite interesting.

What is LiveData?

If you try to find a definition for LiveData, you’ll find that…

Google created Jetpack Navigation to simplify navigation between destinations (such as fragment destinations) and allow defining logical scopes between these destinations using shared navigation graphs.

We can scope ViewModels to the associated NavBackStackEntry of these navigation graphs, and even persist their state across process death using the SavedStateHandle.

However, as a NavController instance is scoped to an Activity, the prevalent pattern for using Jetpack Navigation from a ViewModel has been historically verbose. …

Gabor Varadi

Android dev. Zhuinden, or EpicPandaForce @ SO. Extension function fan #Kotlin, dislikes multiple Activities/Fragment backstack.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store