One Off the Slack

These articles summarize the discussion on a particular thread in the #compose channel of JetBrains’ Slack workspace for Kotlin developers. If you would like to read the original thread, you will need access to that workspace — sign up at https://slack.kotlinlang.org!

Stability Now!

Maik had a MutableList parameter to a MyList() composable and was wondering why MyList() would recompose, even if that MutableList did not change.

The problem is that while Maik knows that the list did not change, Compose does not. As Google’s Jim Sproch put it:

MyList(items) takes in a MutableList, which is (as the name suggests) mutable, so Compose can’t know if that list has been modified or not, so it needs to be conservative and rerun that code. If you use a list implementation that is stable (like SnapshotStateList) then MyList(items) is less likely to run.

Even a List would be insufficient, as that simply prevents one from modifying what elements are in the list — the contents of the elements themselves could change.

In general, composable functions work best with truly immutable contents, and that will require using types that Compose know are truly immutable (e.g., ones with the @Stable annotation).

Jim also points out a key risk:

…keep in mind that your code should NEVER make assumptions about when composables will run. Compose is free to run composable functions for any reason and at any time, at its sole discretion.

This has the potential of being an ongoing problem with Compose development, relying on side-effects from composition. A composable should be idempotent: whether it gets called zero, one, two, or a thousand times should have no impact on the rest of the app.

Posted 2020-09-20, based on https://kotlinlang.slack.com/archives/CJLTWPH7S/p1600333577162900


TextField and Names

Jan Skrasek asked:

Is there any issue/”initiative” to decompose TextField? Such simple thing as setting a background color seems quite impossible. (outline api doesn’t provide bg color property, filled text field applies 0.12% transparency on the passed value…) All building blocks are internal/private

The core problem is that TextField() is a part of the Material Design set of composables, whereas BaseTextField() is the non-Material basis for text entry. Or, as Google’s Ian Lake put it:

I mean, a Material TextField is a very, very specific thing with defined styles from the Material spec. BaseTextField is indeed the non-private building block you’d want to build your own custom styling on top of. Maybe also consider creating issues about what made it difficult to use BastTextField if you want a non-material style

Zhelyazko Atanasov then hit on the core problem: people not realizing that BaseTextField() exists and that TextField() represents a materialized approach:

It’s a bit confusing having a specific implementation of a component (the Material implementation) named after the generic component - TextField, while the barebone, non-specific implementation is BaseTextField. Wouldn’t it be better to rename:

or similar.

Louis noted that Compose UI used to work that way:

That used to be the case, but then we heard the opposite feedback - developers would intuitively reach for TextField first, and be confused because it has no opinionated UX or styling, and requires a lot of work to look like a Material TextField. The current rename was to point developers to the opinionated component first, as this is usually the desired component.

And, as Andrey Mischenko pointed out, the problem is prior solutions getting a bit too cute:

I think a part of expectations that TextField is styled as material design component comes from current situation with Android views, when material library replaces standard views during inflation of layout (edited)

This always worried me with the approach taken by AppCompat and similar libraries. XML elements in layout resources are supposed to indicate the Java class that is the implementation of the View or ViewGroup. AppCompat changes that, swapping in its own classes for the ones declared in the layout. This made AppCompat adoption easier, at the cost of causing some developers to not realize that AppCompat’s widgets were not the same as the framework’s widgets.

This sort of thing could be handled somewhat in documentation, such as mentioning BaseTextField() in the KDocs for TextField().

Posted 2020-09-13, based on https://kotlinlang.slack.com/archives/CJLTWPH7S/p1599494195155900


My Kingdom For a Stable IDE!

Early adopters of Compose are starting to chafe at needing to use Canary releases of Android Studio. Considering that Canary releases might not run without manual intervention, this is not surprising.

Dominic Fisher asked:

Does compose work in stable Android Studio yet? Since it doesn’t need the custom Kotlin compiler build anymore.

The biggest limitation is with setting up the Compose compiler plugin, as Google’s Adam Powell notes:

not without some custom gradle configuration to enable the compiler plugin, since the higher level android gradle plugin options that do it for you are only present in the alpha agp builds

Zach Klippenstein wondered:

Is compose support going to start migrating up to beta, etc with 4.2?

The answer from Google’s Romain Guy unfortunately boils down to ¯\_(ツ)_/¯:

Android Studio and Compose are not synced up for versioning

My interpretation: the Compose team cannot tell the Studio team what it must support. The fact that Compose can work with stock Kotlin builds probably helps and increases the likelihood that 4.2 will continue with Compose support when it progresses from Canary to Beta status. However, there are no guarantees, and the Studio team can do what it wants. We may need to stick to Canary builds for a while longer, as we have since the outset.

Alex Burdusel wants to use a different IDE altogether:

Any guidelines for the gradle configuration for making it work in the stable version? I’m more interested in making it work in Intellij than in AS

The upshot, once again, amounted to ¯\_(ツ)_/¯.

All of this will get sorted out in the fullness of time. The key features are @Preview support and better auto-complete (e.g., to help recommend property delegates). Eventually, the Studio team will ship a stable version that has those. The question then becomes: what portion of that will get migrated to the Android plugin for IntelliJ IDEA? Other IDEs, like Eclipse or Visual Studio Code, would have their own timetables for supporting things like @Preview.

Posted 2020-09-06, based on https://kotlinlang.slack.com/archives/CJLTWPH7S/p1599226474008300


More!

Older “One Off the Slack” articles can be found in the archives.