jetc.dev Newsletter Issue #33

Published: 2020-09-29

This week, we continue banging the drum for using immutable types with Compose. We also look at Hilt and GraphQL with Compose, and we explore how dependency inversion might work with a Compose-based UI. We also watch a Compose-rendered T-Rex run and jump!

One Off the Stack, One Off the Slack

You’ve got questions. That’s understandable!

This week’s options for Stack Overflow questions mostly were incomplete, so let’s focus on Slack instead…

Immutability Is Your Friend

Hardly a week goes by without somebody being bitten in the posterior by trying to use mutable data with Compose. While Compose can use mutable properties and types, they may not trigger recompositions when you mutate their contents. On the whole, Compose works better with immutable types, as we see in this week’s highlighted Slack thread.

Composable Commentary

Posts, videos, and other new information related to Jetpack Compose!

How to Handle Navigation in Jetpack Compose

Gastón Saillén reviews one approach for navigation in Compose, with a custom navigator and nav graph classes reminiscent of the NavController and Kotlin DSL of the Jetpack Navigation component.

Use Jetpack Compose Correctly!

Medium user MR3Y offers up five tips for working with Compose, including implementing custom states and the value of layoutId.

Exploring Jetpack Compose with Hilt and ViewModels

Last week’s issue included a link to Jaewong Eum’s DisneyCompose sample app. This week, Jaewong has a post decribing how it works, including how Hilt was integrated into the app.

Add GraphQL to Your Jetpack Compose Apps

Martin Bonnin shows us how to connect the Apollo-Android GraphQL client up to our composables, using a coroutine-based API mapping GraphQL responses to UI states.

Videos: Jetpack Compose for Beginners

YouTube user Yet Another Dev is publishing a series of screencasts exploring Compose, including looks at themes, Stack(), and scrollable lists.

Jetpack Compose: How to Make a Scrollable List?

Gérard Paligot wrote a Medium post comparing and contrasting ScrollableColumn() and LazyColumnFor() as approaches for creating a scrollable list of content.

Resource Roundup

100% pure code!

Koin Composable Support

Koin is a dependency inversion (DI) system written in Kotlin, used as an alternative to Dagger. The current pre-release build of Koin offers dependency resolution from within a composable, both for arbitrary Koin-supplied objects and specifically for ViewModel instances. For those looking to perhaps use Compose in Kotlin/Multiplatform projects, Koin is an important option, given that it supports KMP while Dagger is tied exclusively to the JVM.

GitHub: skydoves / Landscapist

Jaewong Eum appears again in this issue, this time with another set of image-loading composables, backed by your choice of Glide or Fresco.

Gist: vganin / ComposeNumberPicker.kt

Vsevolod Ganin brings us NumberPicker() composable, complete with fling support!

GitHub: wajahatkarim3 / DinoCompose

Wajahat Karim ported Chrome’s T-Rex themed endless runner game to Compose! Watch out for the cacti!

…And One More Thing

There are many aspects of modern Android app development that we need to work into Compose-based development. Dependency inversion (DI) is one of those. While a lot of DI takes place away from the UI layer, modern activities and fragments still often use some amount of DI, such as for obtaining configured ViewModel instances. So we need to determine where in a composable hierarchy we should be using DI… if anywhere.

Koin’s release of composable DI support, mentioned earlier in this issue, sparked some discussion on this point. Some developers believe that composables should not be interacting with DI services — instead, they should be getting all injectable elements passed into them instead.

Personally, I am skeptical of that argument, for the simple reason that the @Composable annotation is going to be everywhere.

For example, once a Compose-ready edition of the Jetpack Navigation component is ready, my guess is that our Compose activity will look like:

  • onCreate() calling setContent() with a composable lambda, as we have it now

  • That lambda will set up Navigation using the Kotlin DSL

  • Nav destinations will be calls to composable functions

This does not preclude limiting DI to being outside of the composable hierarchy. But that means everything that we are getting from DI that is needed by the UI layer goes in this activity. That seems excessive, particularly for larger apps.

My guess is that we will adopt DI patterns reminiscent of how we handle state. Right now, the state recommendations are:

  • Prefer stateless composables to stateful ones, particularly at leaves of the composable hierarchy

  • For composables that need state, prefer to receive the state via parameters rather than declaring it locally

  • Aim to have your state at the point of commonality: the spot in the composable hierarchy where all consumers of that state descend from

So, for DI, we might wind up with:

  • Prefer composables without DI-provided dependencies, particularly at leaves of the composable hierarchy

  • For composables that need dependencies, prefer to receive them via parameters rather than having it be injected locally

  • Aim to have your injections at the point of commonality: the spot in the composable hierarchy where all consumers of that dependency descend from

But, that is what the next several months are for, as we progress through alpha releases and “kick the tires” on Compose. By the time Compose ships in stable form — and preferably even before a beta — hopefully we will have a pattern that seems reasonable that we can provide to newcomers.