The Jetpack Compose library provides the ability to create declarative and reactive UIs written in Kotlin for Android. It's another attempt to avoid XML layout files by allowing the creation of layouts in a DSL-esque manner. The library borrows heavily from cross-platform application frameworks like React Native and Flutter, but unlike those frameworks, it is meant solely for the Android platform and is written in Kotlin (similar to the Android View DSL library, Anko). While this library will surely continue to grow in prominence, there are some concerns I have about it.

TL;DR

Jetpack Compose is a very intriguing library, but it's coupling of layouts and logic, along with it's inflexibility to adapt to a desired design pattern, are concerning.

Code

The following is a Jetpack Compose example taken from the official tutorial.

@Composable
fun NewsStory() {
    val image = +imageResource(R.drawable.header)

    MaterialTheme {
        Column(
            crossAxisSize = LayoutSize.Expand,
            modifier=Spacing(16.dp)
        ) {
            Container(expanded = true, height = 180.dp) {
                Clip(shape = RoundedCornerShape(8.dp)) {
                    DrawImage(image)
                }
            }

            HeightSpacer(16.dp)

            Text("A day wandering through the sandhills in Shark " +
                "Fin Cove, and a few of the sights I saw",
                maxLines = 2, overflow = TextOverflow.Ellipsis,
                style = (+themeTextStyle { h6 }).withOpacity(0.87f))
            Text("Davenport, California",
                style = (+themeTextStyle { body2 }).withOpacity(0.87f))
            Text("December 2018",
                style = (+themeTextStyle { body2 }).withOpacity(0.6f))
        }
    }
}
        

Concerns

  • Tightly coupled state management and layout logic.
  • Inflexibility to adapt to different design patterns.
  • No support for existing Views, such as, ConstraintLayout and RecyclerView.

Elaborate

  • Tightly coupled state management and layout logic.

The Layout now handles managing it's own state which is different than most currently used approaches where the Layout/View reacts to commands from the Presenter/ViewModel or User input. Instead, this new approach will couple the state management and the layout itself. Some of this maintenance is alleviated by the framework ( `+state { ... }` ), but for more complex state, custom State models will have to be created that conform to the framework using the appropriate annotations. This especially gets troublesome for Kotlin Multi-platform projects where part of the presentation code may be reusable and does not have access to an Android specific framework.

  • Inflexibility to adapt to different design patterns.

This issue is similar to the issue mentioned above with more of a focus on accessing the defined Layouts and Views. The Jetpack Compose library doesn't give you access to the underlying View object created. For instance, Text("") will not return the "TextView" object. This makes it difficult to adapt to different design patterns other than the one the framework enforces. For example, in a Kotlin Multi-platform project, using Model-View-Presenter, the Models, View interfaces, and Presenters may be within a multi-platform presentation module. While the View implementations would be platform specific. Not having access to the underlying view and layout components makes implementing a View interface much more difficult.

  • No support for existing Views, such as, ConstraintLayout and RecyclerView

Most of the examples given from blogs and even the official tutorial are very simple. They showcase an ideal "Hello World" like scenario but they don't showcase a real-world application with all the intracacies that come along with it.

Common and popular layouts for Android that help with some of the complexities involved with layouts in applications are ConstraintLayout and RecyclerView. Since the Jetpack Compose library doesn't use the existing Android View components, it would have to recreate these. That's certainly not a trivial task. But these are two very important components for a proper layout library, and unfortunately, I haven't seen any alternative from Jetpack Compose.

Bonus

With Jetpack Compose, layouts are broken down into @Composable annotated functions. This is a nice approach to separating the complexity and making reusable components. An issue that this presents though, is access to other classes and resources within these functions. Ideally, you would have a Layout class that has constructor injected dependencies which can be accessible from the composable layout functions. But I'm not sure this is the case or if the library would allow this. If it doesn't than this is certainly a concern. Here's an example of what I'm visualizing:

class MyLayout @Inject constructor(private val stringResources: StringResources) : Layout {

    override fun createLayout() = MyComposableFunction()
    
    @Composable
    fun MyComposableFunction() {
        Text(stringResources.helloWorld)
    }
}

End

The Jetpack Compose library is a highly anticipated layout library/framework, especially as the Android Developer Community seeks to move further away from XML based layouts. But this library presents some valid concerns that should not be overlooked when considering the move.