Secure Secrets in Android using Jetpack Security (In-Depth) — Android Security-02

Secure Secrets 🔑 in Android using Jetpack Security (In-Depth) — Android Security-02

In google I/O 2019 Android team released its Security Cryptographic library named Jetpack Security to ease developers in building secured applications.


Secure Secrets 🔑 in Android using Jetpack Security (In-Depth) — Android Security-02 was originally published in Kt. Academy on Medium, where people are continuing the conversation by highlighting and responding to this story.

Continue ReadingSecure Secrets in Android using Jetpack Security (In-Depth) — Android Security-02

How to Secure Secrets in Android-Android Security-01

Security is a key requirement while building an application that’s dealing with APIs, Tokens received from a server, Storing credentials in local DB, Sending secure data onto the network, and many other scenarios.


How to Secure Secrets 🔑 in Android-Android Security-01 was originally published in Kt. Academy on Medium, where people are continuing the conversation by highlighting and responding to this story.

Continue ReadingHow to Secure Secrets in Android-Android Security-01

JetPack Compose  — State Management

IJetPack Compose 🏹 — State Management

It refers to manage the state of the user interface while interacting with widgets like text fields, buttons, radio buttons, etc.

Jetpack compose official

State Management in Android is a complex concept and to know the reason you have to first understand the architectural design of Android and to learn why it’s the key requirement to manage state. The Marcelo Benites article Managing State in Android defines the best description of the state:

The state is an object that is connected/subscribed to one or more widgets, contains data, and eager to update the widgets from that data. If there’s any change happens in data, it notifies all widgets to whom it’s connected. The values of the state are changed at runtime.

In jetpack compose the concept of state management is the same as Observable pattern which stated that if there is any change that occurs in the subscribed object, it triggers all of its dependent objects automatically.

In addition to the above concept, jetpack compose has some functional change, which states that the subscribed @ composable function(s) recomposes itself with the new data when the state/object value is updated and doesn’t affect or update the whole UI.

According to the state management document, jetpack composes support state using two ways:

  • remember { mutableStateOf(…) }
  • MutableStateOf
Current working environment

In the past, we used @Model annotation but it was deprecated in0.1.0-dev12. Then state{} annotation deprecated in 0.1.0-dev16.

Let’s discuss it in detail:

remember { mutableStateOf(…) }

It’s an extended version of State

state approach

This approach is the same as what we did in state the only change we see is the calling. Let see what composable team said about it:

Mark the state composable as deprecated and promote the direct usage of remember { mutableStateOf(…) } instead for better clarity and understanding of the Compose state management API surface. This reduces the overall API surface and the number of concepts for state management and matches the `by mutableStateOf()` pattern for class property delegation.

In this concept, the object is initialized in the same scope where the mutation is implementing. The best possible initialization is inside the @compose function. It also follows the same Kotlin object hierarchical pattern like to pass as a reference to another function. Now, you have a scenario in which you want to mutate the object that’s initialized outside of the scope, then the next approach mutableStateOf is useful.

How to use remember { mutableStateOf(…) } approach

MutableStateOf

mutableStateOf and property delegates

mutableStateOf approach

mutableStateOf API allows us to create MutableState instances outside of class. In this approach, each property is observed individually, so the recompositions you see after this refactor could be more narrow. 🤔

In simple words, it says that read and write operation on each property is watched by compose and if there’s any property change, the composable triggers all of the composed indexes where this property is observed. It also gives us the value property on execution.

See the whole concept of mutableStateOf from the below-defined example:

https://medium.com/media/37747fbc39db213d521e6a1fa8c3bba1/href

If you want to get more clarification then route to my Scaffold tutorial:

AliAzaz/PracticeComposeExamples

The output of scaffold is:

Scaffold output

I hope this article was useful to cover the basic questions regarding Jetpack Compose state management and explore the benefits behind it. Follow me on Twitter for more updates:

Thanks for spending your time reading this article. Please share if you’ve enjoyed it!

Connect with me on my socials and become my friend on Medium, Github, and LinkedIn.

Click 👏 to say “thanks!” and help others find this article.

To be up-to-date with great news on Kt. Academy, subscribe to the newsletter, observe Twitter, and follow us on Medium.

If you need a Kotlin workshop, check how we can help you: kt.academy.


JetPack Compose 🏹 — State Management was originally published in Kt. Academy on Medium, where people are continuing the conversation by highlighting and responding to this story.

Continue ReadingJetPack Compose  — State Management

Android Jetpack Compose Review

Android Jetpack Compose Review

During the last Google I/O the Android team officially announced a brand new Jetpack library named Compose. Trust me when I say this library could change the way developers write Android applications in the future. So let’s review it and write down some thoughts about it.

Android Jetpack Compose Review

Disclaimer: 22 of May 2019, After publishing this blog post the Jetpack Compose team contacted to shed light on some parts  of the post. We recommend you to review them carefully because they point some parts of the implementation they couldn’t cover during the Google I/O talk or the official documentation.

Jetpack Compose aims to be a declarative framework to build Android user interfaces easily using a Kotlin like this:

@Composable
fun RallyApp() {
    RallyTheme {
        Scaffold(appBar = { RallyAppBar() }) {
            RallyBody()
        }
    }
}

@Composable
fun RallyAppBar() {
    Row {
        Text(text = title, style = +themeTextStyle { h4 })
    }
}

@Composable
fun RallyBody() {
    Padding(padding = 16.dp) {
        Column {
            RallyAlertCard()
            HeightSpacer(height = 10.dp)
            RallyAccountsCard()
            HeightSpacer(height = 10.dp)
            RallyBillsCard()
        }
    }
}

The idea is cool, isn’t it? If you are a web developer, you might be familiar with this idea because, years ago, React by Facebook already did this. Based on the concept of web-components, Facebook developers created a framework to be able to build web-based applications in a similar way. However, there are some small details we would like to review 😃

After watching the talk at Google I/O, reading the documentation, and playing with the official repository where this new library is being developed, we’ve got some thoughts we’d like to share with you.

API Design

Once you watch the talk, you notice the Jetpack Compose team has been thinking a lot about the current Android API. They remark how the usage of extensions for some components, and bad decisions they made in the past, doesn’t let the Android API properly evolve. From talking about code reusability to how the usage of the classic OOP design they followed is not generating a maintainable API over time. The team reviews how the current SDK encourage Android devs to keep the state of the app in the view implementation instead of having a single source of truth. After that quick review, they proposed a solution. Inspired by React/Redux, they suggest Jetpack Compose as the solution where developers will no longer create classes extending from the framework but composing their UI using the framework components. And this is awesome!!! However, once you look closer, you start finding some friction points we hope the Google team will solve before the first public release.

The first point we’d like to review is the usage of functions for the components’ declaration. Here you have an example:

@Composable
fun RallyBillsCard(): Unit {
    Card(color = cardInternalColor) {
        Column {
            Padding(padding = 12.dp) {
                Column {
                    Text(text = "Bills", style = +themeTextStyle { subtitle2 })
                    Text(text = "$1,810.00", style = +themeTextStyle { h1 })
                }
            }
        }
    }
}

As you can see, a component can be declared using a function. This might look like an excellent idea, however, we should think about the state of the view. Even when during the talk they mention the usage of a single source of truth and the usage of the lexical scope for the component function, having a local state for our views should be interesting. If instead of using a function for the class declaration we’d use a class we could handle local state in our components easily. With the current implementation, we’d have to wrap all these functions inside a class and keep their state linked to a host component. This is to be able to keep the state in the expected scope outside the setContent method you will find in activities and fragments. Otherwise, the state will be reset once the UI is rendered again, and this forces us to move all the UI state into the app state.

Another interesting point related to the usage of functions is the lack of components lifecycle. If we don’t have a separated lifecycle, how are we going to know if this is the first time we are rendering this component, or it was rendered before? Again, the answer could be to move the state of the view to the app state.

The other small detail can be found in the signature function:

@Composable
fun RallyBillsCard(): Unit {
...
}

Returning Unit will limit the API design from the testing viewpoint. Implementing the API as a huge side effect instead of deferring the computation until the view has to be rendered will not let us test this code using a unit/integration testing approach but the classic UI testing strategy. If you don’t believe me, do what I did. Go to the repository and try to test the code. You can find some examples of tests already written by the team inside the androidTests folder. You’ll see how the usage of an activity just for testing purposes let them write tests asking for the size of the view but not for the information the view is rendering or the style being applied in a friendly way.

If we could just get an instance of the components tree we could make assertions using libraries like Kotlin Snapshot, in the same way, React and Vue.js developers have been doing for the last years. We could write regular unit tests or snapshot tests like these:

fun testRendersTheTitleAsPartOfTheRallyAppBarComponent() {
   val title = "Any title"
   
   val component = RallyApp(title)
   
   assertEquals(title, component.title.text)
}

fun testRendersTheRallyAppBarComponent() {
   val component = RallyApp(title )
   
   component.matchWithSnapshot()
}

@Composable
fun RallyAppBar(title: String) {
    Row {
        Text(text = title, style = +themeTextStyle { h4 })
    }
}

Even when this testing approach is not a silver bullet and we might need to reduce the testing scope to get readable snapshots. Returning the components could simplify the way Android devs test their applications. Even if you don’t think snapshot testing could be a good testing strategy, a good design should let the developer choose the scope of the test or the testing strategy we could use for our automated test suite. However, if we keep returning Unit this will not be possible. If you don’t know what snapshot testing is, take a look at this link.

On the other hand, the usage of return values for our @Composable functions would let us create a truly declarative view tree we could optimize and evaluate in run-time or even in build-time when needed. As you can see, there are some benefits we should consider before the first public release of this library.

Additional notes to the component lifecycle:

After publishing this blog post the Jetpack Compose team contacted me to review this part of the content. They sent me a few notes about some parts of the post:

“We also use Effects for dealing with lifecycle related things. We have a few primitives that you can build a lot on top of to handle this.  For example the `onCommit` and the `onActive` effects. `onActive` runs the first time the component composes, and never after that. In the callback you can also define an `onDispose` callback which will get called as the component is leaving the hierarchy. Similarly, there’s an `onDispose` effect that will just do the latter. `onCommit` is a little more multi-purpose. With no input parameters, It will run every time the component composes. You can also add input parameters, and it will run any time any of them change. This can be useful for a couple of different scenarios.”

@Composable
fun UserProfile(userId: Int) {
   val user = +state<User?>(userId) { null }
   +onCommit(userId) {
       val cancellationToken = UserAPI.get(userId) {
           user.value = it
       }
       onDispose {
           UserAPI.cancel(cancellationToken)
       }
   }
   if (user == null)  {
     Loading()
     return
   }
  Text(text=user.name)
  Image(src=user.photo)
}

“Here we used `userId` as a parameter of `onCommit` so that this code will execute only when the parameter passed into `UserProfile` changes, so we don’t call the API too many times, for instance.”

“You can do some interesting things with this, including building your own more complex reusable effects (again, the concept of “Effect” I believe will eventually get unified with that of a `@Composable` function, so the syntax and keywords and everything will just be the same, but right now they are different).”

“I actually am a fan of snapshot testing, but just don’t think that snapshot testing virtual DOM is the right thing to be doing. I view virtual DOM as an implementation detail and think there can be a lot of problems relying on assertions of shallow renderings of components. I since have come to the conclusion that shallow rendering is probably a mistake. Similarly, I think that anyone relying on the return values of render functions (or composable functions in this case) in tests is probably a bit of a code smell.”

No silver bullets. You still need activities and fragments

During the Google I/O talk, they introduced Compose as a new set of Jetpack UI widget without Activities or Fragments. Just composable components. However, your code will need a component like an Activity, View or Fragment to be able to make it work. This will help you a lot if you want to integrate the usage of the library in just part of your app, but this means any developer using Jetpack Compose will have to learn the old school Android/Fragment/View API. At least, until they develop other components wrapping the navigation or some UI patterns like the usage of tabs into Composable components. This is how an activity using a component would look like:

class RallyActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            AppComponent()
        }
    }

This part will let you use this library in a friendly and compatible way from the beginning and at the same time will work as a workaround for all the design issues you can find in the library.

Where is my state?

During the talk, the team mentioned a lot the usage of a single source of truth and the suggested the usage of a unidirectional data flow. However, this is not as easy as it looks like. To be able to use something like Redux, we will need to be able to create a way to manipulate the state in a friendly way and keep it in memory, being able to mutate it asynchronously when needed without concurrency issues. However, there are no tools like this right now. And this will not be an easy task to implement. The talk describes the usage of LiveData observable fields and data class marked with @Model annotations for the UI updates and the usage of mutable variables as part of the data declaration. Something like this:

@Model
//Look at the VAR username and VAR passwords
class LoginState(var username: String, var password: String) {
    val valid: Boolean get() = username.length > 0 && password.length > 0
    fun login() = Api.login(username, password)
}

Even if we are able to create observable classes using mutable state you still need to keep this class linked to an Activity lifecycle or a Fragment lifecycle because there is no such thing as a unique store you can handle easily for now. So I don’t fully understand how they want to get rid of the state being part of activities and fragments when the proposed implementation doesn’t handle the state lifecycle as Redux already does. I hope they don’t suggest to keep the state as a mutable singleton in the future while using classes with mutable variables annotated with @Model.

Looking at the current state of the library, the only thing I can think about is all the features they still need to develop before considering the first public release. If you want to compare it with the current React/Redux state of the art you can review how React components lifecycle looks like and how these components have to be linked to Redux in these infographics Sergio Gutiérrez designed in a previous blog post:

The lifecycle of a React component:

Android Jetpack Compose Review

Integration between any React component and Redux:

Android Jetpack Compose Review

If you compare it with the current state of the library, there are a lot of pull requests they still have to send before the first release. Maybe, in the future, we can see how they connect Jetpack Compose with libraries like kotlin-redux to be able to handle unidirectional data flows and Arrow for the lenses usage, recursion schemes, side effects, and simple data-types.

Additional notes to the state management:

After publishing this blog post the Jetpack Compose team contacted me to review this part of the content. They sent me a few notes about some parts of the post:

“This isn’t where we’d like people to go, but I can see how this could be easily misinterpreted. Will work on messaging here. We may often hear of “top-down data flow” or “unidirectional data flow” to describe this pattern, and the latter is probably the more accurate term. Composable functions can have local state. Data for a composable function (or “props” to use a React term) is provided to the composable via function parameters, but local state scoped to the composable can be introduced by leveraging Compose’s memoization capabilities. Right now in the repo we have a concept called “Effects” (which may be unifying with Composable functions in the future). You can use these to introduce local state now, either by creating an @Model state class and introducing it with memo, or by using any type and introducing it using state. For example:”

@Composable fun Counter() {
  // introduce a state value (of type `Int`, with initial value of `0`.
  // Note: the `+` syntax is temporary
  val count = +state { 0 }
  // use it to compose your UI. pass it into other composables as parameters
  Text(text="Count: ${count.value}")
  // modify the value inside of event handlers, for instance
  Button(text="Increment, onClick = { count.value += 1; })
}

“Alternatively, use the @Model and memo like I mentioned:”

@Model class CounterState(var count: Int)
@Composable fun Counter() {
  // introduce a CounterState value. Instance will be preserved across compositions.
  // Note: the `+` syntax is temporary
  val count = +memo { Counter(0) }
  // use it to compose your UI. pass it into other composables as parameters
  Text(text="Count: ${count.count}")
  // modify the value inside of event handlers, for instance
  Button(text="Increment, onClick = { count.count += 1; })
}

What about the performance?

Even when they talk about the implementation of a list of components, and they take into account the performance during the talk. They don’t go deep into the library implementation details. They describe the possible implementation of a ScrollingList but if you review the repository there is no such component implemented for now. They describe a promising component like this:

@Composable
fun NewsFeed(stories: LiveData<List<StoryData>>) {
    ScrollingList(stories.observe()) { story ->
        StoryWidget(story)
    }
}

However, this is not part of the repository right now and we will have to wait until a new release in order to check if the suggested implementation looks like this or not.

Also, related to the usage of Unit as return value has another important implication here. As the team is not designing the components API as a set of data we can manipulate easily, there is no way we can compare an already rendered view with a new version of this view with just a bunch of modified values in order to implement an efficient UI rendering from the outside. And this could be really important depending on the final implementation! If you review the React ecosystem, you’ll see how the usage of types for the Virtual DOM design let Facebook engineers implement a smooth UI thanks to the partial update of the device DOM using an efficient and fast diff algorithm. You can read about the Virtual DOM implementation here if you want.

I guess there is an inner mechanism inside the rendering code making all these components efficient when talking about drawing. However, I can’t talk about it because it wasn’t part of the talk and the code I’ve reviewed seems to use canvas API for the component’s rendering.

What if I don’t want to use Jetpack Compose?

Don’t you worry if you want to code like this, but you don’t have time to wait for the final release. You can always create custom views you can compose in your old school layouts and link them with the Jetpack Data Binding library. If you implement your custom view using a single rendering binding method and link the view with a single source of truth implemented using any Redux library you’ll get all the benefits. Don’t forget the layout and your custom views is something you can already compose easily. Keeping the state of the app as part of your model and implementing your custom views as a class with a render function will give you a similar result. Even if you don’t want to use custom views,  you can already do this with your view holders if you don’t follow the Google official guidelines and implement your RecyclerView’s view holder without exposing the internal views and with a method to render the data passed as a parameter. This solution is not based on a nice Kotlin DSL, but might be worthy for you.

Conclusions

The Android team is doing it great. Believe me when I say that this Compose API is way better than the current state of the art of Android development. If you don’t think so try to write a React/ReactNative/Vue application and you’ll better understand what using components like these will be in the future.

Keep in mind that even when this library will help us a lot in the future, the rest of the SDK will have to evolve similarly if we want to improve the way we write our apps. Apart from the design changes the Android Team will implement in the future in the Compose API,  there are a lot of points to enhance in the rest of the SDK: stop returning the execution of the libraries calls as part of the “onActivityResult” methods, let the users get an instance of an activity without initialising the activity lifecycle (really useful for testing), create a friendly API for the animated transitions, etc.

Last but not least, we think releasing a sneak peek like this of the source code, and the examples, is one of the best things Google did. This talk, documentation, and source code let them gather tons of feedback they use for future improvements. There are a lot of things to develop and I hope we will be able to use Compose in all our apps in the future.

References

Here you can find some useful resources about this topic:

Continue ReadingAndroid Jetpack Compose Review

Android Jetpack Compose Review

Android Jetpack Compose Review

During the last Google I/O the Android team officially announced a brand new Jetpack library named Compose. Trust me when I say this library could change the way developers write Android applications in the future. So let’s review it and write down some thoughts about it.

Android Jetpack Compose Review

Disclaimer: 22 of May 2019, After publishing this blog post the Jetpack Compose team contacted to shed light on some parts  of the post. We recommend you to review them carefully because they point some parts of the implementation they couldn’t cover during the Google I/O talk or the official documentation.

Jetpack Compose aims to be a declarative framework to build Android user interfaces easily using a Kotlin like this:

@Composable
fun RallyApp() {
    RallyTheme {
        Scaffold(appBar = { RallyAppBar() }) {
            RallyBody()
        }
    }
}

@Composable
fun RallyAppBar() {
    Row {
        Text(text = title, style = +themeTextStyle { h4 })
    }
}

@Composable
fun RallyBody() {
    Padding(padding = 16.dp) {
        Column {
            RallyAlertCard()
            HeightSpacer(height = 10.dp)
            RallyAccountsCard()
            HeightSpacer(height = 10.dp)
            RallyBillsCard()
        }
    }
}

The idea is cool, isn’t it? If you are a web developer, you might be familiar with this idea because, years ago, React by Facebook already did this. Based on the concept of web-components, Facebook developers created a framework to be able to build web-based applications in a similar way. However, there are some small details we would like to review 😃

After watching the talk at Google I/O, reading the documentation, and playing with the official repository where this new library is being developed, we’ve got some thoughts we’d like to share with you.

API Design

Once you watch the talk, you notice the Jetpack Compose team has been thinking a lot about the current Android API. They remark how the usage of extensions for some components, and bad decisions they made in the past, doesn’t let the Android API properly evolve. From talking about code reusability to how the usage of the classic OOP design they followed is not generating a maintainable API over time. The team reviews how the current SDK encourage Android devs to keep the state of the app in the view implementation instead of having a single source of truth. After that quick review, they proposed a solution. Inspired by React/Redux, they suggest Jetpack Compose as the solution where developers will no longer create classes extending from the framework but composing their UI using the framework components. And this is awesome!!! However, once you look closer, you start finding some friction points we hope the Google team will solve before the first public release.

The first point we’d like to review is the usage of functions for the components’ declaration. Here you have an example:

@Composable
fun RallyBillsCard(): Unit {
    Card(color = cardInternalColor) {
        Column {
            Padding(padding = 12.dp) {
                Column {
                    Text(text = "Bills", style = +themeTextStyle { subtitle2 })
                    Text(text = "$1,810.00", style = +themeTextStyle { h1 })
                }
            }
        }
    }
}

As you can see, a component can be declared using a function. This might look like an excellent idea, however, we should think about the state of the view. Even when during the talk they mention the usage of a single source of truth and the usage of the lexical scope for the component function, having a local state for our views should be interesting. If instead of using a function for the class declaration we’d use a class we could handle local state in our components easily. With the current implementation, we’d have to wrap all these functions inside a class and keep their state linked to a host component. This is to be able to keep the state in the expected scope outside the setContent method you will find in activities and fragments. Otherwise, the state will be reset once the UI is rendered again, and this forces us to move all the UI state into the app state.

Another interesting point related to the usage of functions is the lack of components lifecycle. If we don’t have a separated lifecycle, how are we going to know if this is the first time we are rendering this component, or it was rendered before? Again, the answer could be to move the state of the view to the app state.

The other small detail can be found in the signature function:

@Composable
fun RallyBillsCard(): Unit {
...
}

Returning Unit will limit the API design from the testing viewpoint. Implementing the API as a huge side effect instead of deferring the computation until the view has to be rendered will not let us test this code using a unit/integration testing approach but the classic UI testing strategy. If you don’t believe me, do what I did. Go to the repository and try to test the code. You can find some examples of tests already written by the team inside the androidTests folder. You’ll see how the usage of an activity just for testing purposes let them write tests asking for the size of the view but not for the information the view is rendering or the style being applied in a friendly way.

If we could just get an instance of the components tree we could make assertions using libraries like Kotlin Snapshot, in the same way, React and Vue.js developers have been doing for the last years. We could write regular unit tests or snapshot tests like these:

fun testRendersTheTitleAsPartOfTheRallyAppBarComponent() {
   val title = "Any title"
   
   val component = RallyApp(title)
   
   assertEquals(title, component.title.text)
}

fun testRendersTheRallyAppBarComponent() {
   val component = RallyApp(title )
   
   component.matchWithSnapshot()
}

@Composable
fun RallyAppBar(title: String) {
    Row {
        Text(text = title, style = +themeTextStyle { h4 })
    }
}

Even when this testing approach is not a silver bullet and we might need to reduce the testing scope to get readable snapshots. Returning the components could simplify the way Android devs test their applications. Even if you don’t think snapshot testing could be a good testing strategy, a good design should let the developer choose the scope of the test or the testing strategy we could use for our automated test suite. However, if we keep returning Unit this will not be possible. If you don’t know what snapshot testing is, take a look at this link.

On the other hand, the usage of return values for our @Composable functions would let us create a truly declarative view tree we could optimize and evaluate in run-time or even in build-time when needed. As you can see, there are some benefits we should consider before the first public release of this library.

Additional notes to the component lifecycle:

After publishing this blog post the Jetpack Compose team contacted me to review this part of the content. They sent me a few notes about some parts of the post:

“We also use Effects for dealing with lifecycle related things. We have a few primitives that you can build a lot on top of to handle this.  For example the `onCommit` and the `onActive` effects. `onActive` runs the first time the component composes, and never after that. In the callback you can also define an `onDispose` callback which will get called as the component is leaving the hierarchy. Similarly, there’s an `onDispose` effect that will just do the latter. `onCommit` is a little more multi-purpose. With no input parameters, It will run every time the component composes. You can also add input parameters, and it will run any time any of them change. This can be useful for a couple of different scenarios.”

@Composable
fun UserProfile(userId: Int) {
   val user = +state<User?>(userId) { null }
   +onCommit(userId) {
       val cancellationToken = UserAPI.get(userId) {
           user.value = it
       }
       onDispose {
           UserAPI.cancel(cancellationToken)
       }
   }
   if (user == null)  {
     Loading()
     return
   }
  Text(text=user.name)
  Image(src=user.photo)
}

“Here we used `userId` as a parameter of `onCommit` so that this code will execute only when the parameter passed into `UserProfile` changes, so we don’t call the API too many times, for instance.”

“You can do some interesting things with this, including building your own more complex reusable effects (again, the concept of “Effect” I believe will eventually get unified with that of a `@Composable` function, so the syntax and keywords and everything will just be the same, but right now they are different).”

“I actually am a fan of snapshot testing, but just don’t think that snapshot testing virtual DOM is the right thing to be doing. I view virtual DOM as an implementation detail and think there can be a lot of problems relying on assertions of shallow renderings of components. I since have come to the conclusion that shallow rendering is probably a mistake. Similarly, I think that anyone relying on the return values of render functions (or composable functions in this case) in tests is probably a bit of a code smell.”

No silver bullets. You still need activities and fragments

During the Google I/O talk, they introduced Compose as a new set of Jetpack UI widget without Activities or Fragments. Just composable components. However, your code will need a component like an Activity, View or Fragment to be able to make it work. This will help you a lot if you want to integrate the usage of the library in just part of your app, but this means any developer using Jetpack Compose will have to learn the old school Android/Fragment/View API. At least, until they develop other components wrapping the navigation or some UI patterns like the usage of tabs into Composable components. This is how an activity using a component would look like:

class RallyActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            AppComponent()
        }
    }

This part will let you use this library in a friendly and compatible way from the beginning and at the same time will work as a workaround for all the design issues you can find in the library.

Where is my state?

During the talk, the team mentioned a lot the usage of a single source of truth and the suggested the usage of a unidirectional data flow. However, this is not as easy as it looks like. To be able to use something like Redux, we will need to be able to create a way to manipulate the state in a friendly way and keep it in memory, being able to mutate it asynchronously when needed without concurrency issues. However, there are no tools like this right now. And this will not be an easy task to implement. The talk describes the usage of LiveData observable fields and data class marked with @Model annotations for the UI updates and the usage of mutable variables as part of the data declaration. Something like this:

@Model
//Look at the VAR username and VAR passwords
class LoginState(var username: String, var password: String) {
    val valid: Boolean get() = username.length > 0 && password.length > 0
    fun login() = Api.login(username, password)
}

Even if we are able to create observable classes using mutable state you still need to keep this class linked to an Activity lifecycle or a Fragment lifecycle because there is no such thing as a unique store you can handle easily for now. So I don’t fully understand how they want to get rid of the state being part of activities and fragments when the proposed implementation doesn’t handle the state lifecycle as Redux already does. I hope they don’t suggest to keep the state as a mutable singleton in the future while using classes with mutable variables annotated with @Model.

Looking at the current state of the library, the only thing I can think about is all the features they still need to develop before considering the first public release. If you want to compare it with the current React/Redux state of the art you can review how React components lifecycle looks like and how these components have to be linked to Redux in these infographics Sergio Gutiérrez designed in a previous blog post:

The lifecycle of a React component:

Android Jetpack Compose Review

Integration between any React component and Redux:

Android Jetpack Compose Review

If you compare it with the current state of the library, there are a lot of pull requests they still have to send before the first release. Maybe, in the future, we can see how they connect Jetpack Compose with libraries like kotlin-redux to be able to handle unidirectional data flows and Arrow for the lenses usage, recursion schemes, side effects, and simple data-types.

Additional notes to the state management:

After publishing this blog post the Jetpack Compose team contacted me to review this part of the content. They sent me a few notes about some parts of the post:

“This isn’t where we’d like people to go, but I can see how this could be easily misinterpreted. Will work on messaging here. We may often hear of “top-down data flow” or “unidirectional data flow” to describe this pattern, and the latter is probably the more accurate term. Composable functions can have local state. Data for a composable function (or “props” to use a React term) is provided to the composable via function parameters, but local state scoped to the composable can be introduced by leveraging Compose’s memoization capabilities. Right now in the repo we have a concept called “Effects” (which may be unifying with Composable functions in the future). You can use these to introduce local state now, either by creating an @Model state class and introducing it with memo, or by using any type and introducing it using state. For example:”

@Composable fun Counter() {
  // introduce a state value (of type `Int`, with initial value of `0`.
  // Note: the `+` syntax is temporary
  val count = +state { 0 }
  // use it to compose your UI. pass it into other composables as parameters
  Text(text="Count: ${count.value}")
  // modify the value inside of event handlers, for instance
  Button(text="Increment, onClick = { count.value += 1; })
}

“Alternatively, use the @Model and memo like I mentioned:”

@Model class CounterState(var count: Int)
@Composable fun Counter() {
  // introduce a CounterState value. Instance will be preserved across compositions.
  // Note: the `+` syntax is temporary
  val count = +memo { Counter(0) }
  // use it to compose your UI. pass it into other composables as parameters
  Text(text="Count: ${count.count}")
  // modify the value inside of event handlers, for instance
  Button(text="Increment, onClick = { count.count += 1; })
}

What about the performance?

Even when they talk about the implementation of a list of components, and they take into account the performance during the talk. They don’t go deep into the library implementation details. They describe the possible implementation of a ScrollingList but if you review the repository there is no such component implemented for now. They describe a promising component like this:

@Composable
fun NewsFeed(stories: LiveData<List<StoryData>>) {
    ScrollingList(stories.observe()) { story ->
        StoryWidget(story)
    }
}

However, this is not part of the repository right now and we will have to wait until a new release in order to check if the suggested implementation looks like this or not.

Also, related to the usage of Unit as return value has another important implication here. As the team is not designing the components API as a set of data we can manipulate easily, there is no way we can compare an already rendered view with a new version of this view with just a bunch of modified values in order to implement an efficient UI rendering from the outside. And this could be really important depending on the final implementation! If you review the React ecosystem, you’ll see how the usage of types for the Virtual DOM design let Facebook engineers implement a smooth UI thanks to the partial update of the device DOM using an efficient and fast diff algorithm. You can read about the Virtual DOM implementation here if you want.

I guess there is an inner mechanism inside the rendering code making all these components efficient when talking about drawing. However, I can’t talk about it because it wasn’t part of the talk and the code I’ve reviewed seems to use canvas API for the component’s rendering.

What if I don’t want to use Jetpack Compose?

Don’t you worry if you want to code like this, but you don’t have time to wait for the final release. You can always create custom views you can compose in your old school layouts and link them with the Jetpack Data Binding library. If you implement your custom view using a single rendering binding method and link the view with a single source of truth implemented using any Redux library you’ll get all the benefits. Don’t forget the layout and your custom views is something you can already compose easily. Keeping the state of the app as part of your model and implementing your custom views as a class with a render function will give you a similar result. Even if you don’t want to use custom views,  you can already do this with your view holders if you don’t follow the Google official guidelines and implement your RecyclerView’s view holder without exposing the internal views and with a method to render the data passed as a parameter. This solution is not based on a nice Kotlin DSL, but might be worthy for you.

Conclusions

The Android team is doing it great. Believe me when I say that this Compose API is way better than the current state of the art of Android development. If you don’t think so try to write a React/ReactNative/Vue application and you’ll better understand what using components like these will be in the future.

Keep in mind that even when this library will help us a lot in the future, the rest of the SDK will have to evolve similarly if we want to improve the way we write our apps. Apart from the design changes the Android Team will implement in the future in the Compose API,  there are a lot of points to enhance in the rest of the SDK: stop returning the execution of the libraries calls as part of the “onActivityResult” methods, let the users get an instance of an activity without initialising the activity lifecycle (really useful for testing), create a friendly API for the animated transitions, etc.

Last but not least, we think releasing a sneak peek like this of the source code, and the examples, is one of the best things Google did. This talk, documentation, and source code let them gather tons of feedback they use for future improvements. There are a lot of things to develop and I hope we will be able to use Compose in all our apps in the future.

References

Here you can find some useful resources about this topic:

Continue ReadingAndroid Jetpack Compose Review

Android Jetpack Compose Review

Android Jetpack Compose Review

During the last Google I/O the Android team officially announced a brand new Jetpack library named Compose. Trust me when I say this library could change the way developers write Android applications in the future. So let’s review it and write down some thoughts about it.

Android Jetpack Compose Review

Disclaimer: 22 of May 2019, After publishing this blog post the Jetpack Compose team contacted to shed light on some parts  of the post. We recommend you to review them carefully because they point some parts of the implementation they couldn’t cover during the Google I/O talk or the official documentation.

Jetpack Compose aims to be a declarative framework to build Android user interfaces easily using a Kotlin like this:

@Composable
fun RallyApp() {
    RallyTheme {
        Scaffold(appBar = { RallyAppBar() }) {
            RallyBody()
        }
    }
}

@Composable
fun RallyAppBar() {
    Row {
        Text(text = title, style = +themeTextStyle { h4 })
    }
}

@Composable
fun RallyBody() {
    Padding(padding = 16.dp) {
        Column {
            RallyAlertCard()
            HeightSpacer(height = 10.dp)
            RallyAccountsCard()
            HeightSpacer(height = 10.dp)
            RallyBillsCard()
        }
    }
}

The idea is cool, isn’t it? If you are a web developer, you might be familiar with this idea because, years ago, React by Facebook already did this. Based on the concept of web-components, Facebook developers created a framework to be able to build web-based applications in a similar way. However, there are some small details we would like to review 😃

After watching the talk at Google I/O, reading the documentation, and playing with the official repository where this new library is being developed, we’ve got some thoughts we’d like to share with you.

API Design

Once you watch the talk, you notice the Jetpack Compose team has been thinking a lot about the current Android API. They remark how the usage of extensions for some components, and bad decisions they made in the past, doesn’t let the Android API properly evolve. From talking about code reusability to how the usage of the classic OOP design they followed is not generating a maintainable API over time. The team reviews how the current SDK encourage Android devs to keep the state of the app in the view implementation instead of having a single source of truth. After that quick review, they proposed a solution. Inspired by React/Redux, they suggest Jetpack Compose as the solution where developers will no longer create classes extending from the framework but composing their UI using the framework components. And this is awesome!!! However, once you look closer, you start finding some friction points we hope the Google team will solve before the first public release.

The first point we’d like to review is the usage of functions for the components’ declaration. Here you have an example:

@Composable
fun RallyBillsCard(): Unit {
    Card(color = cardInternalColor) {
        Column {
            Padding(padding = 12.dp) {
                Column {
                    Text(text = "Bills", style = +themeTextStyle { subtitle2 })
                    Text(text = "$1,810.00", style = +themeTextStyle { h1 })
                }
            }
        }
    }
}

As you can see, a component can be declared using a function. This might look like an excellent idea, however, we should think about the state of the view. Even when during the talk they mention the usage of a single source of truth and the usage of the lexical scope for the component function, having a local state for our views should be interesting. If instead of using a function for the class declaration we’d use a class we could handle local state in our components easily. With the current implementation, we’d have to wrap all these functions inside a class and keep their state linked to a host component. This is to be able to keep the state in the expected scope outside the setContent method you will find in activities and fragments. Otherwise, the state will be reset once the UI is rendered again, and this forces us to move all the UI state into the app state.

Another interesting point related to the usage of functions is the lack of components lifecycle. If we don’t have a separated lifecycle, how are we going to know if this is the first time we are rendering this component, or it was rendered before? Again, the answer could be to move the state of the view to the app state.

The other small detail can be found in the signature function:

@Composable
fun RallyBillsCard(): Unit {
...
}

Returning Unit will limit the API design from the testing viewpoint. Implementing the API as a huge side effect instead of deferring the computation until the view has to be rendered will not let us test this code using a unit/integration testing approach but the classic UI testing strategy. If you don’t believe me, do what I did. Go to the repository and try to test the code. You can find some examples of tests already written by the team inside the androidTests folder. You’ll see how the usage of an activity just for testing purposes let them write tests asking for the size of the view but not for the information the view is rendering or the style being applied in a friendly way.

If we could just get an instance of the components tree we could make assertions using libraries like Kotlin Snapshot, in the same way, React and Vue.js developers have been doing for the last years. We could write regular unit tests or snapshot tests like these:

fun testRendersTheTitleAsPartOfTheRallyAppBarComponent() {
   val title = "Any title"
   
   val component = RallyApp(title)
   
   assertEquals(title, component.title.text)
}

fun testRendersTheRallyAppBarComponent() {
   val component = RallyApp(title )
   
   component.matchWithSnapshot()
}

@Composable
fun RallyAppBar(title: String) {
    Row {
        Text(text = title, style = +themeTextStyle { h4 })
    }
}

Even when this testing approach is not a silver bullet and we might need to reduce the testing scope to get readable snapshots. Returning the components could simplify the way Android devs test their applications. Even if you don’t think snapshot testing could be a good testing strategy, a good design should let the developer choose the scope of the test or the testing strategy we could use for our automated test suite. However, if we keep returning Unit this will not be possible. If you don’t know what snapshot testing is, take a look at this link.

On the other hand, the usage of return values for our @Composable functions would let us create a truly declarative view tree we could optimize and evaluate in run-time or even in build-time when needed. As you can see, there are some benefits we should consider before the first public release of this library.

Additional notes to the component lifecycle:

After publishing this blog post the Jetpack Compose team contacted me to review this part of the content. They sent me a few notes about some parts of the post:

“We also use Effects for dealing with lifecycle related things. We have a few primitives that you can build a lot on top of to handle this.  For example the `onCommit` and the `onActive` effects. `onActive` runs the first time the component composes, and never after that. In the callback you can also define an `onDispose` callback which will get called as the component is leaving the hierarchy. Similarly, there’s an `onDispose` effect that will just do the latter. `onCommit` is a little more multi-purpose. With no input parameters, It will run every time the component composes. You can also add input parameters, and it will run any time any of them change. This can be useful for a couple of different scenarios.”

@Composable
fun UserProfile(userId: Int) {
   val user = +state<User?>(userId) { null }
   +onCommit(userId) {
       val cancellationToken = UserAPI.get(userId) {
           user.value = it
       }
       onDispose {
           UserAPI.cancel(cancellationToken)
       }
   }
   if (user == null)  {
     Loading()
     return
   }
  Text(text=user.name)
  Image(src=user.photo)
}

“Here we used `userId` as a parameter of `onCommit` so that this code will execute only when the parameter passed into `UserProfile` changes, so we don’t call the API too many times, for instance.”

“You can do some interesting things with this, including building your own more complex reusable effects (again, the concept of “Effect” I believe will eventually get unified with that of a `@Composable` function, so the syntax and keywords and everything will just be the same, but right now they are different).”

“I actually am a fan of snapshot testing, but just don’t think that snapshot testing virtual DOM is the right thing to be doing. I view virtual DOM as an implementation detail and think there can be a lot of problems relying on assertions of shallow renderings of components. I since have come to the conclusion that shallow rendering is probably a mistake. Similarly, I think that anyone relying on the return values of render functions (or composable functions in this case) in tests is probably a bit of a code smell.”

No silver bullets. You still need activities and fragments

During the Google I/O talk, they introduced Compose as a new set of Jetpack UI widget without Activities or Fragments. Just composable components. However, your code will need a component like an Activity, View or Fragment to be able to make it work. This will help you a lot if you want to integrate the usage of the library in just part of your app, but this means any developer using Jetpack Compose will have to learn the old school Android/Fragment/View API. At least, until they develop other components wrapping the navigation or some UI patterns like the usage of tabs into Composable components. This is how an activity using a component would look like:

class RallyActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            AppComponent()
        }
    }

This part will let you use this library in a friendly and compatible way from the beginning and at the same time will work as a workaround for all the design issues you can find in the library.

Where is my state?

During the talk, the team mentioned a lot the usage of a single source of truth and the suggested the usage of a unidirectional data flow. However, this is not as easy as it looks like. To be able to use something like Redux, we will need to be able to create a way to manipulate the state in a friendly way and keep it in memory, being able to mutate it asynchronously when needed without concurrency issues. However, there are no tools like this right now. And this will not be an easy task to implement. The talk describes the usage of LiveData observable fields and data class marked with @Model annotations for the UI updates and the usage of mutable variables as part of the data declaration. Something like this:

@Model
//Look at the VAR username and VAR passwords
class LoginState(var username: String, var password: String) {
    val valid: Boolean get() = username.length > 0 && password.length > 0
    fun login() = Api.login(username, password)
}

Even if we are able to create observable classes using mutable state you still need to keep this class linked to an Activity lifecycle or a Fragment lifecycle because there is no such thing as a unique store you can handle easily for now. So I don’t fully understand how they want to get rid of the state being part of activities and fragments when the proposed implementation doesn’t handle the state lifecycle as Redux already does. I hope they don’t suggest to keep the state as a mutable singleton in the future while using classes with mutable variables annotated with @Model.

Looking at the current state of the library, the only thing I can think about is all the features they still need to develop before considering the first public release. If you want to compare it with the current React/Redux state of the art you can review how React components lifecycle looks like and how these components have to be linked to Redux in these infographics Sergio Gutiérrez designed in a previous blog post:

The lifecycle of a React component:

Android Jetpack Compose Review

Integration between any React component and Redux:

Android Jetpack Compose Review

If you compare it with the current state of the library, there are a lot of pull requests they still have to send before the first release. Maybe, in the future, we can see how they connect Jetpack Compose with libraries like kotlin-redux to be able to handle unidirectional data flows and Arrow for the lenses usage, recursion schemes, side effects, and simple data-types.

Additional notes to the state management:

After publishing this blog post the Jetpack Compose team contacted me to review this part of the content. They sent me a few notes about some parts of the post:

“This isn’t where we’d like people to go, but I can see how this could be easily misinterpreted. Will work on messaging here. We may often hear of “top-down data flow” or “unidirectional data flow” to describe this pattern, and the latter is probably the more accurate term. Composable functions can have local state. Data for a composable function (or “props” to use a React term) is provided to the composable via function parameters, but local state scoped to the composable can be introduced by leveraging Compose’s memoization capabilities. Right now in the repo we have a concept called “Effects” (which may be unifying with Composable functions in the future). You can use these to introduce local state now, either by creating an @Model state class and introducing it with memo, or by using any type and introducing it using state. For example:”

@Composable fun Counter() {
  // introduce a state value (of type `Int`, with initial value of `0`.
  // Note: the `+` syntax is temporary
  val count = +state { 0 }
  // use it to compose your UI. pass it into other composables as parameters
  Text(text="Count: ${count.value}")
  // modify the value inside of event handlers, for instance
  Button(text="Increment, onClick = { count.value += 1; })
}

“Alternatively, use the @Model and memo like I mentioned:”

@Model class CounterState(var count: Int)
@Composable fun Counter() {
  // introduce a CounterState value. Instance will be preserved across compositions.
  // Note: the `+` syntax is temporary
  val count = +memo { Counter(0) }
  // use it to compose your UI. pass it into other composables as parameters
  Text(text="Count: ${count.count}")
  // modify the value inside of event handlers, for instance
  Button(text="Increment, onClick = { count.count += 1; })
}

What about the performance?

Even when they talk about the implementation of a list of components, and they take into account the performance during the talk. They don’t go deep into the library implementation details. They describe the possible implementation of a ScrollingList but if you review the repository there is no such component implemented for now. They describe a promising component like this:

@Composable
fun NewsFeed(stories: LiveData<List<StoryData>>) {
    ScrollingList(stories.observe()) { story ->
        StoryWidget(story)
    }
}

However, this is not part of the repository right now and we will have to wait until a new release in order to check if the suggested implementation looks like this or not.

Also, related to the usage of Unit as return value has another important implication here. As the team is not designing the components API as a set of data we can manipulate easily, there is no way we can compare an already rendered view with a new version of this view with just a bunch of modified values in order to implement an efficient UI rendering from the outside. And this could be really important depending on the final implementation! If you review the React ecosystem, you’ll see how the usage of types for the Virtual DOM design let Facebook engineers implement a smooth UI thanks to the partial update of the device DOM using an efficient and fast diff algorithm. You can read about the Virtual DOM implementation here if you want.

I guess there is an inner mechanism inside the rendering code making all these components efficient when talking about drawing. However, I can’t talk about it because it wasn’t part of the talk and the code I’ve reviewed seems to use canvas API for the component’s rendering.

What if I don’t want to use Jetpack Compose?

Don’t you worry if you want to code like this, but you don’t have time to wait for the final release. You can always create custom views you can compose in your old school layouts and link them with the Jetpack Data Binding library. If you implement your custom view using a single rendering binding method and link the view with a single source of truth implemented using any Redux library you’ll get all the benefits. Don’t forget the layout and your custom views is something you can already compose easily. Keeping the state of the app as part of your model and implementing your custom views as a class with a render function will give you a similar result. Even if you don’t want to use custom views,  you can already do this with your view holders if you don’t follow the Google official guidelines and implement your RecyclerView’s view holder without exposing the internal views and with a method to render the data passed as a parameter. This solution is not based on a nice Kotlin DSL, but might be worthy for you.

Conclusions

The Android team is doing it great. Believe me when I say that this Compose API is way better than the current state of the art of Android development. If you don’t think so try to write a React/ReactNative/Vue application and you’ll better understand what using components like these will be in the future.

Keep in mind that even when this library will help us a lot in the future, the rest of the SDK will have to evolve similarly if we want to improve the way we write our apps. Apart from the design changes the Android Team will implement in the future in the Compose API,  there are a lot of points to enhance in the rest of the SDK: stop returning the execution of the libraries calls as part of the “onActivityResult” methods, let the users get an instance of an activity without initialising the activity lifecycle (really useful for testing), create a friendly API for the animated transitions, etc.

Last but not least, we think releasing a sneak peek like this of the source code, and the examples, is one of the best things Google did. This talk, documentation, and source code let them gather tons of feedback they use for future improvements. There are a lot of things to develop and I hope we will be able to use Compose in all our apps in the future.

References

Here you can find some useful resources about this topic:

Continue ReadingAndroid Jetpack Compose Review

Android Jetpack Compose Review

Android Jetpack Compose Review

During the last Google I/O the Android team officially announced a brand new Jetpack library named Compose. Trust me when I say this library could change the way developers write Android applications in the future. So let’s review it and write down some thoughts about it.

Android Jetpack Compose Review

Disclaimer: 22 of May 2019, After publishing this blog post the Jetpack Compose team contacted to shed light on some parts  of the post. We recommend you to review them carefully because they point some parts of the implementation they couldn’t cover during the Google I/O talk or the official documentation.

Jetpack Compose aims to be a declarative framework to build Android user interfaces easily using a Kotlin like this:

@Composable
fun RallyApp() {
    RallyTheme {
        Scaffold(appBar = { RallyAppBar() }) {
            RallyBody()
        }
    }
}

@Composable
fun RallyAppBar() {
    Row {
        Text(text = title, style = +themeTextStyle { h4 })
    }
}

@Composable
fun RallyBody() {
    Padding(padding = 16.dp) {
        Column {
            RallyAlertCard()
            HeightSpacer(height = 10.dp)
            RallyAccountsCard()
            HeightSpacer(height = 10.dp)
            RallyBillsCard()
        }
    }
}

The idea is cool, isn’t it? If you are a web developer, you might be familiar with this idea because, years ago, React by Facebook already did this. Based on the concept of web-components, Facebook developers created a framework to be able to build web-based applications in a similar way. However, there are some small details we would like to review 😃

After watching the talk at Google I/O, reading the documentation, and playing with the official repository where this new library is being developed, we’ve got some thoughts we’d like to share with you.

API Design

Once you watch the talk, you notice the Jetpack Compose team has been thinking a lot about the current Android API. They remark how the usage of extensions for some components, and bad decisions they made in the past, doesn’t let the Android API properly evolve. From talking about code reusability to how the usage of the classic OOP design they followed is not generating a maintainable API over time. The team reviews how the current SDK encourage Android devs to keep the state of the app in the view implementation instead of having a single source of truth. After that quick review, they proposed a solution. Inspired by React/Redux, they suggest Jetpack Compose as the solution where developers will no longer create classes extending from the framework but composing their UI using the framework components. And this is awesome!!! However, once you look closer, you start finding some friction points we hope the Google team will solve before the first public release.

The first point we’d like to review is the usage of functions for the components’ declaration. Here you have an example:

@Composable
fun RallyBillsCard(): Unit {
    Card(color = cardInternalColor) {
        Column {
            Padding(padding = 12.dp) {
                Column {
                    Text(text = "Bills", style = +themeTextStyle { subtitle2 })
                    Text(text = "$1,810.00", style = +themeTextStyle { h1 })
                }
            }
        }
    }
}

As you can see, a component can be declared using a function. This might look like an excellent idea, however, we should think about the state of the view. Even when during the talk they mention the usage of a single source of truth and the usage of the lexical scope for the component function, having a local state for our views should be interesting. If instead of using a function for the class declaration we’d use a class we could handle local state in our components easily. With the current implementation, we’d have to wrap all these functions inside a class and keep their state linked to a host component. This is to be able to keep the state in the expected scope outside the setContent method you will find in activities and fragments. Otherwise, the state will be reset once the UI is rendered again, and this forces us to move all the UI state into the app state.

Another interesting point related to the usage of functions is the lack of components lifecycle. If we don’t have a separated lifecycle, how are we going to know if this is the first time we are rendering this component, or it was rendered before? Again, the answer could be to move the state of the view to the app state.

The other small detail can be found in the signature function:

@Composable
fun RallyBillsCard(): Unit {
...
}

Returning Unit will limit the API design from the testing viewpoint. Implementing the API as a huge side effect instead of deferring the computation until the view has to be rendered will not let us test this code using a unit/integration testing approach but the classic UI testing strategy. If you don’t believe me, do what I did. Go to the repository and try to test the code. You can find some examples of tests already written by the team inside the androidTests folder. You’ll see how the usage of an activity just for testing purposes let them write tests asking for the size of the view but not for the information the view is rendering or the style being applied in a friendly way.

If we could just get an instance of the components tree we could make assertions using libraries like Kotlin Snapshot, in the same way, React and Vue.js developers have been doing for the last years. We could write regular unit tests or snapshot tests like these:

fun testRendersTheTitleAsPartOfTheRallyAppBarComponent() {
   val title = "Any title"
   
   val component = RallyApp(title)
   
   assertEquals(title, component.title.text)
}

fun testRendersTheRallyAppBarComponent() {
   val component = RallyApp(title )
   
   component.matchWithSnapshot()
}

@Composable
fun RallyAppBar(title: String) {
    Row {
        Text(text = title, style = +themeTextStyle { h4 })
    }
}

Even when this testing approach is not a silver bullet and we might need to reduce the testing scope to get readable snapshots. Returning the components could simplify the way Android devs test their applications. Even if you don’t think snapshot testing could be a good testing strategy, a good design should let the developer choose the scope of the test or the testing strategy we could use for our automated test suite. However, if we keep returning Unit this will not be possible. If you don’t know what snapshot testing is, take a look at this link.

On the other hand, the usage of return values for our @Composable functions would let us create a truly declarative view tree we could optimize and evaluate in run-time or even in build-time when needed. As you can see, there are some benefits we should consider before the first public release of this library.

Additional notes to the component lifecycle:

After publishing this blog post the Jetpack Compose team contacted me to review this part of the content. They sent me a few notes about some parts of the post:

“We also use Effects for dealing with lifecycle related things. We have a few primitives that you can build a lot on top of to handle this.  For example the `onCommit` and the `onActive` effects. `onActive` runs the first time the component composes, and never after that. In the callback you can also define an `onDispose` callback which will get called as the component is leaving the hierarchy. Similarly, there’s an `onDispose` effect that will just do the latter. `onCommit` is a little more multi-purpose. With no input parameters, It will run every time the component composes. You can also add input parameters, and it will run any time any of them change. This can be useful for a couple of different scenarios.”

@Composable
fun UserProfile(userId: Int) {
   val user = +state<User?>(userId) { null }
   +onCommit(userId) {
       val cancellationToken = UserAPI.get(userId) {
           user.value = it
       }
       onDispose {
           UserAPI.cancel(cancellationToken)
       }
   }
   if (user == null)  {
     Loading()
     return
   }
  Text(text=user.name)
  Image(src=user.photo)
}

“Here we used `userId` as a parameter of `onCommit` so that this code will execute only when the parameter passed into `UserProfile` changes, so we don’t call the API too many times, for instance.”

“You can do some interesting things with this, including building your own more complex reusable effects (again, the concept of “Effect” I believe will eventually get unified with that of a `@Composable` function, so the syntax and keywords and everything will just be the same, but right now they are different).”

“I actually am a fan of snapshot testing, but just don’t think that snapshot testing virtual DOM is the right thing to be doing. I view virtual DOM as an implementation detail and think there can be a lot of problems relying on assertions of shallow renderings of components. I since have come to the conclusion that shallow rendering is probably a mistake. Similarly, I think that anyone relying on the return values of render functions (or composable functions in this case) in tests is probably a bit of a code smell.”

No silver bullets. You still need activities and fragments

During the Google I/O talk, they introduced Compose as a new set of Jetpack UI widget without Activities or Fragments. Just composable components. However, your code will need a component like an Activity, View or Fragment to be able to make it work. This will help you a lot if you want to integrate the usage of the library in just part of your app, but this means any developer using Jetpack Compose will have to learn the old school Android/Fragment/View API. At least, until they develop other components wrapping the navigation or some UI patterns like the usage of tabs into Composable components. This is how an activity using a component would look like:

class RallyActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            AppComponent()
        }
    }

This part will let you use this library in a friendly and compatible way from the beginning and at the same time will work as a workaround for all the design issues you can find in the library.

Where is my state?

During the talk, the team mentioned a lot the usage of a single source of truth and the suggested the usage of a unidirectional data flow. However, this is not as easy as it looks like. To be able to use something like Redux, we will need to be able to create a way to manipulate the state in a friendly way and keep it in memory, being able to mutate it asynchronously when needed without concurrency issues. However, there are no tools like this right now. And this will not be an easy task to implement. The talk describes the usage of LiveData observable fields and data class marked with @Model annotations for the UI updates and the usage of mutable variables as part of the data declaration. Something like this:

@Model
//Look at the VAR username and VAR passwords
class LoginState(var username: String, var password: String) {
    val valid: Boolean get() = username.length > 0 && password.length > 0
    fun login() = Api.login(username, password)
}

Even if we are able to create observable classes using mutable state you still need to keep this class linked to an Activity lifecycle or a Fragment lifecycle because there is no such thing as a unique store you can handle easily for now. So I don’t fully understand how they want to get rid of the state being part of activities and fragments when the proposed implementation doesn’t handle the state lifecycle as Redux already does. I hope they don’t suggest to keep the state as a mutable singleton in the future while using classes with mutable variables annotated with @Model.

Looking at the current state of the library, the only thing I can think about is all the features they still need to develop before considering the first public release. If you want to compare it with the current React/Redux state of the art you can review how React components lifecycle looks like and how these components have to be linked to Redux in these infographics Sergio Gutiérrez designed in a previous blog post:

The lifecycle of a React component:

Android Jetpack Compose Review

Integration between any React component and Redux:

Android Jetpack Compose Review

If you compare it with the current state of the library, there are a lot of pull requests they still have to send before the first release. Maybe, in the future, we can see how they connect Jetpack Compose with libraries like kotlin-redux to be able to handle unidirectional data flows and Arrow for the lenses usage, recursion schemes, side effects, and simple data-types.

Additional notes to the state management:

After publishing this blog post the Jetpack Compose team contacted me to review this part of the content. They sent me a few notes about some parts of the post:

“This isn’t where we’d like people to go, but I can see how this could be easily misinterpreted. Will work on messaging here. We may often hear of “top-down data flow” or “unidirectional data flow” to describe this pattern, and the latter is probably the more accurate term. Composable functions can have local state. Data for a composable function (or “props” to use a React term) is provided to the composable via function parameters, but local state scoped to the composable can be introduced by leveraging Compose’s memoization capabilities. Right now in the repo we have a concept called “Effects” (which may be unifying with Composable functions in the future). You can use these to introduce local state now, either by creating an @Model state class and introducing it with memo, or by using any type and introducing it using state. For example:”

@Composable fun Counter() {
  // introduce a state value (of type `Int`, with initial value of `0`.
  // Note: the `+` syntax is temporary
  val count = +state { 0 }
  // use it to compose your UI. pass it into other composables as parameters
  Text(text="Count: ${count.value}")
  // modify the value inside of event handlers, for instance
  Button(text="Increment, onClick = { count.value += 1; })
}

“Alternatively, use the @Model and memo like I mentioned:”

@Model class CounterState(var count: Int)
@Composable fun Counter() {
  // introduce a CounterState value. Instance will be preserved across compositions.
  // Note: the `+` syntax is temporary
  val count = +memo { Counter(0) }
  // use it to compose your UI. pass it into other composables as parameters
  Text(text="Count: ${count.count}")
  // modify the value inside of event handlers, for instance
  Button(text="Increment, onClick = { count.count += 1; })
}

What about the performance?

Even when they talk about the implementation of a list of components, and they take into account the performance during the talk. They don’t go deep into the library implementation details. They describe the possible implementation of a ScrollingList but if you review the repository there is no such component implemented for now. They describe a promising component like this:

@Composable
fun NewsFeed(stories: LiveData<List<StoryData>>) {
    ScrollingList(stories.observe()) { story ->
        StoryWidget(story)
    }
}

However, this is not part of the repository right now and we will have to wait until a new release in order to check if the suggested implementation looks like this or not.

Also, related to the usage of Unit as return value has another important implication here. As the team is not designing the components API as a set of data we can manipulate easily, there is no way we can compare an already rendered view with a new version of this view with just a bunch of modified values in order to implement an efficient UI rendering from the outside. And this could be really important depending on the final implementation! If you review the React ecosystem, you’ll see how the usage of types for the Virtual DOM design let Facebook engineers implement a smooth UI thanks to the partial update of the device DOM using an efficient and fast diff algorithm. You can read about the Virtual DOM implementation here if you want.

I guess there is an inner mechanism inside the rendering code making all these components efficient when talking about drawing. However, I can’t talk about it because it wasn’t part of the talk and the code I’ve reviewed seems to use canvas API for the component’s rendering.

What if I don’t want to use Jetpack Compose?

Don’t you worry if you want to code like this, but you don’t have time to wait for the final release. You can always create custom views you can compose in your old school layouts and link them with the Jetpack Data Binding library. If you implement your custom view using a single rendering binding method and link the view with a single source of truth implemented using any Redux library you’ll get all the benefits. Don’t forget the layout and your custom views is something you can already compose easily. Keeping the state of the app as part of your model and implementing your custom views as a class with a render function will give you a similar result. Even if you don’t want to use custom views,  you can already do this with your view holders if you don’t follow the Google official guidelines and implement your RecyclerView’s view holder without exposing the internal views and with a method to render the data passed as a parameter. This solution is not based on a nice Kotlin DSL, but might be worthy for you.

Conclusions

The Android team is doing it great. Believe me when I say that this Compose API is way better than the current state of the art of Android development. If you don’t think so try to write a React/ReactNative/Vue application and you’ll better understand what using components like these will be in the future.

Keep in mind that even when this library will help us a lot in the future, the rest of the SDK will have to evolve similarly if we want to improve the way we write our apps. Apart from the design changes the Android Team will implement in the future in the Compose API,  there are a lot of points to enhance in the rest of the SDK: stop returning the execution of the libraries calls as part of the “onActivityResult” methods, let the users get an instance of an activity without initialising the activity lifecycle (really useful for testing), create a friendly API for the animated transitions, etc.

Last but not least, we think releasing a sneak peek like this of the source code, and the examples, is one of the best things Google did. This talk, documentation, and source code let them gather tons of feedback they use for future improvements. There are a lot of things to develop and I hope we will be able to use Compose in all our apps in the future.

References

Here you can find some useful resources about this topic:

Continue ReadingAndroid Jetpack Compose Review

Android Jetpack Compose Review

Android Jetpack Compose Review

During the last Google I/O the Android team officially announced a brand new Jetpack library named Compose. Trust me when I say this library could change the way developers write Android applications in the future. So let’s review it and write down some thoughts about it.

Android Jetpack Compose Review

Disclaimer: 22 of May 2019, After publishing this blog post the Jetpack Compose team contacted to shed light on some parts  of the post. We recommend you to review them carefully because they point some parts of the implementation they couldn’t cover during the Google I/O talk or the official documentation.

Jetpack Compose aims to be a declarative framework to build Android user interfaces easily using a Kotlin like this:

@Composable
fun RallyApp() {
    RallyTheme {
        Scaffold(appBar = { RallyAppBar() }) {
            RallyBody()
        }
    }
}

@Composable
fun RallyAppBar() {
    Row {
        Text(text = title, style = +themeTextStyle { h4 })
    }
}

@Composable
fun RallyBody() {
    Padding(padding = 16.dp) {
        Column {
            RallyAlertCard()
            HeightSpacer(height = 10.dp)
            RallyAccountsCard()
            HeightSpacer(height = 10.dp)
            RallyBillsCard()
        }
    }
}

The idea is cool, isn’t it? If you are a web developer, you might be familiar with this idea because, years ago, React by Facebook already did this. Based on the concept of web-components, Facebook developers created a framework to be able to build web-based applications in a similar way. However, there are some small details we would like to review 😃

After watching the talk at Google I/O, reading the documentation, and playing with the official repository where this new library is being developed, we’ve got some thoughts we’d like to share with you.

API Design

Once you watch the talk, you notice the Jetpack Compose team has been thinking a lot about the current Android API. They remark how the usage of extensions for some components, and bad decisions they made in the past, doesn’t let the Android API properly evolve. From talking about code reusability to how the usage of the classic OOP design they followed is not generating a maintainable API over time. The team reviews how the current SDK encourage Android devs to keep the state of the app in the view implementation instead of having a single source of truth. After that quick review, they proposed a solution. Inspired by React/Redux, they suggest Jetpack Compose as the solution where developers will no longer create classes extending from the framework but composing their UI using the framework components. And this is awesome!!! However, once you look closer, you start finding some friction points we hope the Google team will solve before the first public release.

The first point we’d like to review is the usage of functions for the components’ declaration. Here you have an example:

@Composable
fun RallyBillsCard(): Unit {
    Card(color = cardInternalColor) {
        Column {
            Padding(padding = 12.dp) {
                Column {
                    Text(text = "Bills", style = +themeTextStyle { subtitle2 })
                    Text(text = "$1,810.00", style = +themeTextStyle { h1 })
                }
            }
        }
    }
}

As you can see, a component can be declared using a function. This might look like an excellent idea, however, we should think about the state of the view. Even when during the talk they mention the usage of a single source of truth and the usage of the lexical scope for the component function, having a local state for our views should be interesting. If instead of using a function for the class declaration we’d use a class we could handle local state in our components easily. With the current implementation, we’d have to wrap all these functions inside a class and keep their state linked to a host component. This is to be able to keep the state in the expected scope outside the setContent method you will find in activities and fragments. Otherwise, the state will be reset once the UI is rendered again, and this forces us to move all the UI state into the app state.

Another interesting point related to the usage of functions is the lack of components lifecycle. If we don’t have a separated lifecycle, how are we going to know if this is the first time we are rendering this component, or it was rendered before? Again, the answer could be to move the state of the view to the app state.

The other small detail can be found in the signature function:

@Composable
fun RallyBillsCard(): Unit {
...
}

Returning Unit will limit the API design from the testing viewpoint. Implementing the API as a huge side effect instead of deferring the computation until the view has to be rendered will not let us test this code using a unit/integration testing approach but the classic UI testing strategy. If you don’t believe me, do what I did. Go to the repository and try to test the code. You can find some examples of tests already written by the team inside the androidTests folder. You’ll see how the usage of an activity just for testing purposes let them write tests asking for the size of the view but not for the information the view is rendering or the style being applied in a friendly way.

If we could just get an instance of the components tree we could make assertions using libraries like Kotlin Snapshot, in the same way, React and Vue.js developers have been doing for the last years. We could write regular unit tests or snapshot tests like these:

fun testRendersTheTitleAsPartOfTheRallyAppBarComponent() {
   val title = "Any title"
   
   val component = RallyApp(title)
   
   assertEquals(title, component.title.text)
}

fun testRendersTheRallyAppBarComponent() {
   val component = RallyApp(title )
   
   component.matchWithSnapshot()
}

@Composable
fun RallyAppBar(title: String) {
    Row {
        Text(text = title, style = +themeTextStyle { h4 })
    }
}

Even when this testing approach is not a silver bullet and we might need to reduce the testing scope to get readable snapshots. Returning the components could simplify the way Android devs test their applications. Even if you don’t think snapshot testing could be a good testing strategy, a good design should let the developer choose the scope of the test or the testing strategy we could use for our automated test suite. However, if we keep returning Unit this will not be possible. If you don’t know what snapshot testing is, take a look at this link.

On the other hand, the usage of return values for our @Composable functions would let us create a truly declarative view tree we could optimize and evaluate in run-time or even in build-time when needed. As you can see, there are some benefits we should consider before the first public release of this library.

Additional notes to the component lifecycle:

After publishing this blog post the Jetpack Compose team contacted me to review this part of the content. They sent me a few notes about some parts of the post:

“We also use Effects for dealing with lifecycle related things. We have a few primitives that you can build a lot on top of to handle this.  For example the `onCommit` and the `onActive` effects. `onActive` runs the first time the component composes, and never after that. In the callback you can also define an `onDispose` callback which will get called as the component is leaving the hierarchy. Similarly, there’s an `onDispose` effect that will just do the latter. `onCommit` is a little more multi-purpose. With no input parameters, It will run every time the component composes. You can also add input parameters, and it will run any time any of them change. This can be useful for a couple of different scenarios.”

@Composable
fun UserProfile(userId: Int) {
   val user = +state<User?>(userId) { null }
   +onCommit(userId) {
       val cancellationToken = UserAPI.get(userId) {
           user.value = it
       }
       onDispose {
           UserAPI.cancel(cancellationToken)
       }
   }
   if (user == null)  {
     Loading()
     return
   }
  Text(text=user.name)
  Image(src=user.photo)
}

“Here we used `userId` as a parameter of `onCommit` so that this code will execute only when the parameter passed into `UserProfile` changes, so we don’t call the API too many times, for instance.”

“You can do some interesting things with this, including building your own more complex reusable effects (again, the concept of “Effect” I believe will eventually get unified with that of a `@Composable` function, so the syntax and keywords and everything will just be the same, but right now they are different).”

“I actually am a fan of snapshot testing, but just don’t think that snapshot testing virtual DOM is the right thing to be doing. I view virtual DOM as an implementation detail and think there can be a lot of problems relying on assertions of shallow renderings of components. I since have come to the conclusion that shallow rendering is probably a mistake. Similarly, I think that anyone relying on the return values of render functions (or composable functions in this case) in tests is probably a bit of a code smell.”

No silver bullets. You still need activities and fragments

During the Google I/O talk, they introduced Compose as a new set of Jetpack UI widget without Activities or Fragments. Just composable components. However, your code will need a component like an Activity, View or Fragment to be able to make it work. This will help you a lot if you want to integrate the usage of the library in just part of your app, but this means any developer using Jetpack Compose will have to learn the old school Android/Fragment/View API. At least, until they develop other components wrapping the navigation or some UI patterns like the usage of tabs into Composable components. This is how an activity using a component would look like:

class RallyActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            AppComponent()
        }
    }

This part will let you use this library in a friendly and compatible way from the beginning and at the same time will work as a workaround for all the design issues you can find in the library.

Where is my state?

During the talk, the team mentioned a lot the usage of a single source of truth and the suggested the usage of a unidirectional data flow. However, this is not as easy as it looks like. To be able to use something like Redux, we will need to be able to create a way to manipulate the state in a friendly way and keep it in memory, being able to mutate it asynchronously when needed without concurrency issues. However, there are no tools like this right now. And this will not be an easy task to implement. The talk describes the usage of LiveData observable fields and data class marked with @Model annotations for the UI updates and the usage of mutable variables as part of the data declaration. Something like this:

@Model
//Look at the VAR username and VAR passwords
class LoginState(var username: String, var password: String) {
    val valid: Boolean get() = username.length > 0 && password.length > 0
    fun login() = Api.login(username, password)
}

Even if we are able to create observable classes using mutable state you still need to keep this class linked to an Activity lifecycle or a Fragment lifecycle because there is no such thing as a unique store you can handle easily for now. So I don’t fully understand how they want to get rid of the state being part of activities and fragments when the proposed implementation doesn’t handle the state lifecycle as Redux already does. I hope they don’t suggest to keep the state as a mutable singleton in the future while using classes with mutable variables annotated with @Model.

Looking at the current state of the library, the only thing I can think about is all the features they still need to develop before considering the first public release. If you want to compare it with the current React/Redux state of the art you can review how React components lifecycle looks like and how these components have to be linked to Redux in these infographics Sergio Gutiérrez designed in a previous blog post:

The lifecycle of a React component:

Android Jetpack Compose Review

Integration between any React component and Redux:

Android Jetpack Compose Review

If you compare it with the current state of the library, there are a lot of pull requests they still have to send before the first release. Maybe, in the future, we can see how they connect Jetpack Compose with libraries like kotlin-redux to be able to handle unidirectional data flows and Arrow for the lenses usage, recursion schemes, side effects, and simple data-types.

Additional notes to the state management:

After publishing this blog post the Jetpack Compose team contacted me to review this part of the content. They sent me a few notes about some parts of the post:

“This isn’t where we’d like people to go, but I can see how this could be easily misinterpreted. Will work on messaging here. We may often hear of “top-down data flow” or “unidirectional data flow” to describe this pattern, and the latter is probably the more accurate term. Composable functions can have local state. Data for a composable function (or “props” to use a React term) is provided to the composable via function parameters, but local state scoped to the composable can be introduced by leveraging Compose’s memoization capabilities. Right now in the repo we have a concept called “Effects” (which may be unifying with Composable functions in the future). You can use these to introduce local state now, either by creating an @Model state class and introducing it with memo, or by using any type and introducing it using state. For example:”

@Composable fun Counter() {
  // introduce a state value (of type `Int`, with initial value of `0`.
  // Note: the `+` syntax is temporary
  val count = +state { 0 }
  // use it to compose your UI. pass it into other composables as parameters
  Text(text="Count: ${count.value}")
  // modify the value inside of event handlers, for instance
  Button(text="Increment, onClick = { count.value += 1; })
}

“Alternatively, use the @Model and memo like I mentioned:”

@Model class CounterState(var count: Int)
@Composable fun Counter() {
  // introduce a CounterState value. Instance will be preserved across compositions.
  // Note: the `+` syntax is temporary
  val count = +memo { Counter(0) }
  // use it to compose your UI. pass it into other composables as parameters
  Text(text="Count: ${count.count}")
  // modify the value inside of event handlers, for instance
  Button(text="Increment, onClick = { count.count += 1; })
}

What about the performance?

Even when they talk about the implementation of a list of components, and they take into account the performance during the talk. They don’t go deep into the library implementation details. They describe the possible implementation of a ScrollingList but if you review the repository there is no such component implemented for now. They describe a promising component like this:

@Composable
fun NewsFeed(stories: LiveData<List<StoryData>>) {
    ScrollingList(stories.observe()) { story ->
        StoryWidget(story)
    }
}

However, this is not part of the repository right now and we will have to wait until a new release in order to check if the suggested implementation looks like this or not.

Also, related to the usage of Unit as return value has another important implication here. As the team is not designing the components API as a set of data we can manipulate easily, there is no way we can compare an already rendered view with a new version of this view with just a bunch of modified values in order to implement an efficient UI rendering from the outside. And this could be really important depending on the final implementation! If you review the React ecosystem, you’ll see how the usage of types for the Virtual DOM design let Facebook engineers implement a smooth UI thanks to the partial update of the device DOM using an efficient and fast diff algorithm. You can read about the Virtual DOM implementation here if you want.

I guess there is an inner mechanism inside the rendering code making all these components efficient when talking about drawing. However, I can’t talk about it because it wasn’t part of the talk and the code I’ve reviewed seems to use canvas API for the component’s rendering.

What if I don’t want to use Jetpack Compose?

Don’t you worry if you want to code like this, but you don’t have time to wait for the final release. You can always create custom views you can compose in your old school layouts and link them with the Jetpack Data Binding library. If you implement your custom view using a single rendering binding method and link the view with a single source of truth implemented using any Redux library you’ll get all the benefits. Don’t forget the layout and your custom views is something you can already compose easily. Keeping the state of the app as part of your model and implementing your custom views as a class with a render function will give you a similar result. Even if you don’t want to use custom views,  you can already do this with your view holders if you don’t follow the Google official guidelines and implement your RecyclerView’s view holder without exposing the internal views and with a method to render the data passed as a parameter. This solution is not based on a nice Kotlin DSL, but might be worthy for you.

Conclusions

The Android team is doing it great. Believe me when I say that this Compose API is way better than the current state of the art of Android development. If you don’t think so try to write a React/ReactNative/Vue application and you’ll better understand what using components like these will be in the future.

Keep in mind that even when this library will help us a lot in the future, the rest of the SDK will have to evolve similarly if we want to improve the way we write our apps. Apart from the design changes the Android Team will implement in the future in the Compose API,  there are a lot of points to enhance in the rest of the SDK: stop returning the execution of the libraries calls as part of the “onActivityResult” methods, let the users get an instance of an activity without initialising the activity lifecycle (really useful for testing), create a friendly API for the animated transitions, etc.

Last but not least, we think releasing a sneak peek like this of the source code, and the examples, is one of the best things Google did. This talk, documentation, and source code let them gather tons of feedback they use for future improvements. There are a lot of things to develop and I hope we will be able to use Compose in all our apps in the future.

References

Here you can find some useful resources about this topic:

Continue ReadingAndroid Jetpack Compose Review

Android Jetpack Compose Review

Android Jetpack Compose Review

During the last Google I/O the Android team officially announced a brand new Jetpack library named Compose. Trust me when I say this library could change the way developers write Android applications in the future. So let’s review it and write down some thoughts about it.

Android Jetpack Compose Review

Disclaimer: 22 of May 2019, After publishing this blog post the Jetpack Compose team contacted to shed light on some parts  of the post. We recommend you to review them carefully because they point some parts of the implementation they couldn’t cover during the Google I/O talk or the official documentation.

Jetpack Compose aims to be a declarative framework to build Android user interfaces easily using a Kotlin like this:

@Composable
fun RallyApp() {
    RallyTheme {
        Scaffold(appBar = { RallyAppBar() }) {
            RallyBody()
        }
    }
}

@Composable
fun RallyAppBar() {
    Row {
        Text(text = title, style = +themeTextStyle { h4 })
    }
}

@Composable
fun RallyBody() {
    Padding(padding = 16.dp) {
        Column {
            RallyAlertCard()
            HeightSpacer(height = 10.dp)
            RallyAccountsCard()
            HeightSpacer(height = 10.dp)
            RallyBillsCard()
        }
    }
}

The idea is cool, isn’t it? If you are a web developer, you might be familiar with this idea because, years ago, React by Facebook already did this. Based on the concept of web-components, Facebook developers created a framework to be able to build web-based applications in a similar way. However, there are some small details we would like to review 😃

After watching the talk at Google I/O, reading the documentation, and playing with the official repository where this new library is being developed, we’ve got some thoughts we’d like to share with you.

API Design

Once you watch the talk, you notice the Jetpack Compose team has been thinking a lot about the current Android API. They remark how the usage of extensions for some components, and bad decisions they made in the past, doesn’t let the Android API properly evolve. From talking about code reusability to how the usage of the classic OOP design they followed is not generating a maintainable API over time. The team reviews how the current SDK encourage Android devs to keep the state of the app in the view implementation instead of having a single source of truth. After that quick review, they proposed a solution. Inspired by React/Redux, they suggest Jetpack Compose as the solution where developers will no longer create classes extending from the framework but composing their UI using the framework components. And this is awesome!!! However, once you look closer, you start finding some friction points we hope the Google team will solve before the first public release.

The first point we’d like to review is the usage of functions for the components’ declaration. Here you have an example:

@Composable
fun RallyBillsCard(): Unit {
    Card(color = cardInternalColor) {
        Column {
            Padding(padding = 12.dp) {
                Column {
                    Text(text = "Bills", style = +themeTextStyle { subtitle2 })
                    Text(text = "$1,810.00", style = +themeTextStyle { h1 })
                }
            }
        }
    }
}

As you can see, a component can be declared using a function. This might look like an excellent idea, however, we should think about the state of the view. Even when during the talk they mention the usage of a single source of truth and the usage of the lexical scope for the component function, having a local state for our views should be interesting. If instead of using a function for the class declaration we’d use a class we could handle local state in our components easily. With the current implementation, we’d have to wrap all these functions inside a class and keep their state linked to a host component. This is to be able to keep the state in the expected scope outside the setContent method you will find in activities and fragments. Otherwise, the state will be reset once the UI is rendered again, and this forces us to move all the UI state into the app state.

Another interesting point related to the usage of functions is the lack of components lifecycle. If we don’t have a separated lifecycle, how are we going to know if this is the first time we are rendering this component, or it was rendered before? Again, the answer could be to move the state of the view to the app state.

The other small detail can be found in the signature function:

@Composable
fun RallyBillsCard(): Unit {
...
}

Returning Unit will limit the API design from the testing viewpoint. Implementing the API as a huge side effect instead of deferring the computation until the view has to be rendered will not let us test this code using a unit/integration testing approach but the classic UI testing strategy. If you don’t believe me, do what I did. Go to the repository and try to test the code. You can find some examples of tests already written by the team inside the androidTests folder. You’ll see how the usage of an activity just for testing purposes let them write tests asking for the size of the view but not for the information the view is rendering or the style being applied in a friendly way.

If we could just get an instance of the components tree we could make assertions using libraries like Kotlin Snapshot, in the same way, React and Vue.js developers have been doing for the last years. We could write regular unit tests or snapshot tests like these:

fun testRendersTheTitleAsPartOfTheRallyAppBarComponent() {
   val title = "Any title"
   
   val component = RallyApp(title)
   
   assertEquals(title, component.title.text)
}

fun testRendersTheRallyAppBarComponent() {
   val component = RallyApp(title )
   
   component.matchWithSnapshot()
}

@Composable
fun RallyAppBar(title: String) {
    Row {
        Text(text = title, style = +themeTextStyle { h4 })
    }
}

Even when this testing approach is not a silver bullet and we might need to reduce the testing scope to get readable snapshots. Returning the components could simplify the way Android devs test their applications. Even if you don’t think snapshot testing could be a good testing strategy, a good design should let the developer choose the scope of the test or the testing strategy we could use for our automated test suite. However, if we keep returning Unit this will not be possible. If you don’t know what snapshot testing is, take a look at this link.

On the other hand, the usage of return values for our @Composable functions would let us create a truly declarative view tree we could optimize and evaluate in run-time or even in build-time when needed. As you can see, there are some benefits we should consider before the first public release of this library.

Additional notes to the component lifecycle:

After publishing this blog post the Jetpack Compose team contacted me to review this part of the content. They sent me a few notes about some parts of the post:

“We also use Effects for dealing with lifecycle related things. We have a few primitives that you can build a lot on top of to handle this.  For example the `onCommit` and the `onActive` effects. `onActive` runs the first time the component composes, and never after that. In the callback you can also define an `onDispose` callback which will get called as the component is leaving the hierarchy. Similarly, there’s an `onDispose` effect that will just do the latter. `onCommit` is a little more multi-purpose. With no input parameters, It will run every time the component composes. You can also add input parameters, and it will run any time any of them change. This can be useful for a couple of different scenarios.”

@Composable
fun UserProfile(userId: Int) {
   val user = +state<User?>(userId) { null }
   +onCommit(userId) {
       val cancellationToken = UserAPI.get(userId) {
           user.value = it
       }
       onDispose {
           UserAPI.cancel(cancellationToken)
       }
   }
   if (user == null)  {
     Loading()
     return
   }
  Text(text=user.name)
  Image(src=user.photo)
}

“Here we used `userId` as a parameter of `onCommit` so that this code will execute only when the parameter passed into `UserProfile` changes, so we don’t call the API too many times, for instance.”

“You can do some interesting things with this, including building your own more complex reusable effects (again, the concept of “Effect” I believe will eventually get unified with that of a `@Composable` function, so the syntax and keywords and everything will just be the same, but right now they are different).”

“I actually am a fan of snapshot testing, but just don’t think that snapshot testing virtual DOM is the right thing to be doing. I view virtual DOM as an implementation detail and think there can be a lot of problems relying on assertions of shallow renderings of components. I since have come to the conclusion that shallow rendering is probably a mistake. Similarly, I think that anyone relying on the return values of render functions (or composable functions in this case) in tests is probably a bit of a code smell.”

No silver bullets. You still need activities and fragments

During the Google I/O talk, they introduced Compose as a new set of Jetpack UI widget without Activities or Fragments. Just composable components. However, your code will need a component like an Activity, View or Fragment to be able to make it work. This will help you a lot if you want to integrate the usage of the library in just part of your app, but this means any developer using Jetpack Compose will have to learn the old school Android/Fragment/View API. At least, until they develop other components wrapping the navigation or some UI patterns like the usage of tabs into Composable components. This is how an activity using a component would look like:

class RallyActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            AppComponent()
        }
    }

This part will let you use this library in a friendly and compatible way from the beginning and at the same time will work as a workaround for all the design issues you can find in the library.

Where is my state?

During the talk, the team mentioned a lot the usage of a single source of truth and the suggested the usage of a unidirectional data flow. However, this is not as easy as it looks like. To be able to use something like Redux, we will need to be able to create a way to manipulate the state in a friendly way and keep it in memory, being able to mutate it asynchronously when needed without concurrency issues. However, there are no tools like this right now. And this will not be an easy task to implement. The talk describes the usage of LiveData observable fields and data class marked with @Model annotations for the UI updates and the usage of mutable variables as part of the data declaration. Something like this:

@Model
//Look at the VAR username and VAR passwords
class LoginState(var username: String, var password: String) {
    val valid: Boolean get() = username.length > 0 && password.length > 0
    fun login() = Api.login(username, password)
}

Even if we are able to create observable classes using mutable state you still need to keep this class linked to an Activity lifecycle or a Fragment lifecycle because there is no such thing as a unique store you can handle easily for now. So I don’t fully understand how they want to get rid of the state being part of activities and fragments when the proposed implementation doesn’t handle the state lifecycle as Redux already does. I hope they don’t suggest to keep the state as a mutable singleton in the future while using classes with mutable variables annotated with @Model.

Looking at the current state of the library, the only thing I can think about is all the features they still need to develop before considering the first public release. If you want to compare it with the current React/Redux state of the art you can review how React components lifecycle looks like and how these components have to be linked to Redux in these infographics Sergio Gutiérrez designed in a previous blog post:

The lifecycle of a React component:

Android Jetpack Compose Review

Integration between any React component and Redux:

Android Jetpack Compose Review

If you compare it with the current state of the library, there are a lot of pull requests they still have to send before the first release. Maybe, in the future, we can see how they connect Jetpack Compose with libraries like kotlin-redux to be able to handle unidirectional data flows and Arrow for the lenses usage, recursion schemes, side effects, and simple data-types.

Additional notes to the state management:

After publishing this blog post the Jetpack Compose team contacted me to review this part of the content. They sent me a few notes about some parts of the post:

“This isn’t where we’d like people to go, but I can see how this could be easily misinterpreted. Will work on messaging here. We may often hear of “top-down data flow” or “unidirectional data flow” to describe this pattern, and the latter is probably the more accurate term. Composable functions can have local state. Data for a composable function (or “props” to use a React term) is provided to the composable via function parameters, but local state scoped to the composable can be introduced by leveraging Compose’s memoization capabilities. Right now in the repo we have a concept called “Effects” (which may be unifying with Composable functions in the future). You can use these to introduce local state now, either by creating an @Model state class and introducing it with memo, or by using any type and introducing it using state. For example:”

@Composable fun Counter() {
  // introduce a state value (of type `Int`, with initial value of `0`.
  // Note: the `+` syntax is temporary
  val count = +state { 0 }
  // use it to compose your UI. pass it into other composables as parameters
  Text(text="Count: ${count.value}")
  // modify the value inside of event handlers, for instance
  Button(text="Increment, onClick = { count.value += 1; })
}

“Alternatively, use the @Model and memo like I mentioned:”

@Model class CounterState(var count: Int)
@Composable fun Counter() {
  // introduce a CounterState value. Instance will be preserved across compositions.
  // Note: the `+` syntax is temporary
  val count = +memo { Counter(0) }
  // use it to compose your UI. pass it into other composables as parameters
  Text(text="Count: ${count.count}")
  // modify the value inside of event handlers, for instance
  Button(text="Increment, onClick = { count.count += 1; })
}

What about the performance?

Even when they talk about the implementation of a list of components, and they take into account the performance during the talk. They don’t go deep into the library implementation details. They describe the possible implementation of a ScrollingList but if you review the repository there is no such component implemented for now. They describe a promising component like this:

@Composable
fun NewsFeed(stories: LiveData<List<StoryData>>) {
    ScrollingList(stories.observe()) { story ->
        StoryWidget(story)
    }
}

However, this is not part of the repository right now and we will have to wait until a new release in order to check if the suggested implementation looks like this or not.

Also, related to the usage of Unit as return value has another important implication here. As the team is not designing the components API as a set of data we can manipulate easily, there is no way we can compare an already rendered view with a new version of this view with just a bunch of modified values in order to implement an efficient UI rendering from the outside. And this could be really important depending on the final implementation! If you review the React ecosystem, you’ll see how the usage of types for the Virtual DOM design let Facebook engineers implement a smooth UI thanks to the partial update of the device DOM using an efficient and fast diff algorithm. You can read about the Virtual DOM implementation here if you want.

I guess there is an inner mechanism inside the rendering code making all these components efficient when talking about drawing. However, I can’t talk about it because it wasn’t part of the talk and the code I’ve reviewed seems to use canvas API for the component’s rendering.

What if I don’t want to use Jetpack Compose?

Don’t you worry if you want to code like this, but you don’t have time to wait for the final release. You can always create custom views you can compose in your old school layouts and link them with the Jetpack Data Binding library. If you implement your custom view using a single rendering binding method and link the view with a single source of truth implemented using any Redux library you’ll get all the benefits. Don’t forget the layout and your custom views is something you can already compose easily. Keeping the state of the app as part of your model and implementing your custom views as a class with a render function will give you a similar result. Even if you don’t want to use custom views,  you can already do this with your view holders if you don’t follow the Google official guidelines and implement your RecyclerView’s view holder without exposing the internal views and with a method to render the data passed as a parameter. This solution is not based on a nice Kotlin DSL, but might be worthy for you.

Conclusions

The Android team is doing it great. Believe me when I say that this Compose API is way better than the current state of the art of Android development. If you don’t think so try to write a React/ReactNative/Vue application and you’ll better understand what using components like these will be in the future.

Keep in mind that even when this library will help us a lot in the future, the rest of the SDK will have to evolve similarly if we want to improve the way we write our apps. Apart from the design changes the Android Team will implement in the future in the Compose API,  there are a lot of points to enhance in the rest of the SDK: stop returning the execution of the libraries calls as part of the “onActivityResult” methods, let the users get an instance of an activity without initialising the activity lifecycle (really useful for testing), create a friendly API for the animated transitions, etc.

Last but not least, we think releasing a sneak peek like this of the source code, and the examples, is one of the best things Google did. This talk, documentation, and source code let them gather tons of feedback they use for future improvements. There are a lot of things to develop and I hope we will be able to use Compose in all our apps in the future.

References

Here you can find some useful resources about this topic:

Continue ReadingAndroid Jetpack Compose Review

Android Jetpack Compose Review

Android Jetpack Compose Review

During the last Google I/O the Android team officially announced a brand new Jetpack library named Compose. Trust me when I say this library could change the way developers write Android applications in the future. So let’s review it and write down some thoughts about it.

Android Jetpack Compose Review

Disclaimer: 22 of May 2019, After publishing this blog post the Jetpack Compose team contacted to shed light on some parts  of the post. We recommend you to review them carefully because they point some parts of the implementation they couldn’t cover during the Google I/O talk or the official documentation.

Jetpack Compose aims to be a declarative framework to build Android user interfaces easily using a Kotlin like this:

@Composable
fun RallyApp() {
    RallyTheme {
        Scaffold(appBar = { RallyAppBar() }) {
            RallyBody()
        }
    }
}

@Composable
fun RallyAppBar() {
    Row {
        Text(text = title, style = +themeTextStyle { h4 })
    }
}

@Composable
fun RallyBody() {
    Padding(padding = 16.dp) {
        Column {
            RallyAlertCard()
            HeightSpacer(height = 10.dp)
            RallyAccountsCard()
            HeightSpacer(height = 10.dp)
            RallyBillsCard()
        }
    }
}

The idea is cool, isn’t it? If you are a web developer, you might be familiar with this idea because, years ago, React by Facebook already did this. Based on the concept of web-components, Facebook developers created a framework to be able to build web-based applications in a similar way. However, there are some small details we would like to review 😃

After watching the talk at Google I/O, reading the documentation, and playing with the official repository where this new library is being developed, we’ve got some thoughts we’d like to share with you.

API Design

Once you watch the talk, you notice the Jetpack Compose team has been thinking a lot about the current Android API. They remark how the usage of extensions for some components, and bad decisions they made in the past, doesn’t let the Android API properly evolve. From talking about code reusability to how the usage of the classic OOP design they followed is not generating a maintainable API over time. The team reviews how the current SDK encourage Android devs to keep the state of the app in the view implementation instead of having a single source of truth. After that quick review, they proposed a solution. Inspired by React/Redux, they suggest Jetpack Compose as the solution where developers will no longer create classes extending from the framework but composing their UI using the framework components. And this is awesome!!! However, once you look closer, you start finding some friction points we hope the Google team will solve before the first public release.

The first point we’d like to review is the usage of functions for the components’ declaration. Here you have an example:

@Composable
fun RallyBillsCard(): Unit {
    Card(color = cardInternalColor) {
        Column {
            Padding(padding = 12.dp) {
                Column {
                    Text(text = "Bills", style = +themeTextStyle { subtitle2 })
                    Text(text = "$1,810.00", style = +themeTextStyle { h1 })
                }
            }
        }
    }
}

As you can see, a component can be declared using a function. This might look like an excellent idea, however, we should think about the state of the view. Even when during the talk they mention the usage of a single source of truth and the usage of the lexical scope for the component function, having a local state for our views should be interesting. If instead of using a function for the class declaration we’d use a class we could handle local state in our components easily. With the current implementation, we’d have to wrap all these functions inside a class and keep their state linked to a host component. This is to be able to keep the state in the expected scope outside the setContent method you will find in activities and fragments. Otherwise, the state will be reset once the UI is rendered again, and this forces us to move all the UI state into the app state.

Another interesting point related to the usage of functions is the lack of components lifecycle. If we don’t have a separated lifecycle, how are we going to know if this is the first time we are rendering this component, or it was rendered before? Again, the answer could be to move the state of the view to the app state.

The other small detail can be found in the signature function:

@Composable
fun RallyBillsCard(): Unit {
...
}

Returning Unit will limit the API design from the testing viewpoint. Implementing the API as a huge side effect instead of deferring the computation until the view has to be rendered will not let us test this code using a unit/integration testing approach but the classic UI testing strategy. If you don’t believe me, do what I did. Go to the repository and try to test the code. You can find some examples of tests already written by the team inside the androidTests folder. You’ll see how the usage of an activity just for testing purposes let them write tests asking for the size of the view but not for the information the view is rendering or the style being applied in a friendly way.

If we could just get an instance of the components tree we could make assertions using libraries like Kotlin Snapshot, in the same way, React and Vue.js developers have been doing for the last years. We could write regular unit tests or snapshot tests like these:

fun testRendersTheTitleAsPartOfTheRallyAppBarComponent() {
   val title = "Any title"
   
   val component = RallyApp(title)
   
   assertEquals(title, component.title.text)
}

fun testRendersTheRallyAppBarComponent() {
   val component = RallyApp(title )
   
   component.matchWithSnapshot()
}

@Composable
fun RallyAppBar(title: String) {
    Row {
        Text(text = title, style = +themeTextStyle { h4 })
    }
}

Even when this testing approach is not a silver bullet and we might need to reduce the testing scope to get readable snapshots. Returning the components could simplify the way Android devs test their applications. Even if you don’t think snapshot testing could be a good testing strategy, a good design should let the developer choose the scope of the test or the testing strategy we could use for our automated test suite. However, if we keep returning Unit this will not be possible. If you don’t know what snapshot testing is, take a look at this link.

On the other hand, the usage of return values for our @Composable functions would let us create a truly declarative view tree we could optimize and evaluate in run-time or even in build-time when needed. As you can see, there are some benefits we should consider before the first public release of this library.

Additional notes to the component lifecycle:

After publishing this blog post the Jetpack Compose team contacted me to review this part of the content. They sent me a few notes about some parts of the post:

“We also use Effects for dealing with lifecycle related things. We have a few primitives that you can build a lot on top of to handle this.  For example the `onCommit` and the `onActive` effects. `onActive` runs the first time the component composes, and never after that. In the callback you can also define an `onDispose` callback which will get called as the component is leaving the hierarchy. Similarly, there’s an `onDispose` effect that will just do the latter. `onCommit` is a little more multi-purpose. With no input parameters, It will run every time the component composes. You can also add input parameters, and it will run any time any of them change. This can be useful for a couple of different scenarios.”

@Composable
fun UserProfile(userId: Int) {
   val user = +state<User?>(userId) { null }
   +onCommit(userId) {
       val cancellationToken = UserAPI.get(userId) {
           user.value = it
       }
       onDispose {
           UserAPI.cancel(cancellationToken)
       }
   }
   if (user == null)  {
     Loading()
     return
   }
  Text(text=user.name)
  Image(src=user.photo)
}

“Here we used `userId` as a parameter of `onCommit` so that this code will execute only when the parameter passed into `UserProfile` changes, so we don’t call the API too many times, for instance.”

“You can do some interesting things with this, including building your own more complex reusable effects (again, the concept of “Effect” I believe will eventually get unified with that of a `@Composable` function, so the syntax and keywords and everything will just be the same, but right now they are different).”

“I actually am a fan of snapshot testing, but just don’t think that snapshot testing virtual DOM is the right thing to be doing. I view virtual DOM as an implementation detail and think there can be a lot of problems relying on assertions of shallow renderings of components. I since have come to the conclusion that shallow rendering is probably a mistake. Similarly, I think that anyone relying on the return values of render functions (or composable functions in this case) in tests is probably a bit of a code smell.”

No silver bullets. You still need activities and fragments

During the Google I/O talk, they introduced Compose as a new set of Jetpack UI widget without Activities or Fragments. Just composable components. However, your code will need a component like an Activity, View or Fragment to be able to make it work. This will help you a lot if you want to integrate the usage of the library in just part of your app, but this means any developer using Jetpack Compose will have to learn the old school Android/Fragment/View API. At least, until they develop other components wrapping the navigation or some UI patterns like the usage of tabs into Composable components. This is how an activity using a component would look like:

class RallyActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            AppComponent()
        }
    }

This part will let you use this library in a friendly and compatible way from the beginning and at the same time will work as a workaround for all the design issues you can find in the library.

Where is my state?

During the talk, the team mentioned a lot the usage of a single source of truth and the suggested the usage of a unidirectional data flow. However, this is not as easy as it looks like. To be able to use something like Redux, we will need to be able to create a way to manipulate the state in a friendly way and keep it in memory, being able to mutate it asynchronously when needed without concurrency issues. However, there are no tools like this right now. And this will not be an easy task to implement. The talk describes the usage of LiveData observable fields and data class marked with @Model annotations for the UI updates and the usage of mutable variables as part of the data declaration. Something like this:

@Model
//Look at the VAR username and VAR passwords
class LoginState(var username: String, var password: String) {
    val valid: Boolean get() = username.length > 0 && password.length > 0
    fun login() = Api.login(username, password)
}

Even if we are able to create observable classes using mutable state you still need to keep this class linked to an Activity lifecycle or a Fragment lifecycle because there is no such thing as a unique store you can handle easily for now. So I don’t fully understand how they want to get rid of the state being part of activities and fragments when the proposed implementation doesn’t handle the state lifecycle as Redux already does. I hope they don’t suggest to keep the state as a mutable singleton in the future while using classes with mutable variables annotated with @Model.

Looking at the current state of the library, the only thing I can think about is all the features they still need to develop before considering the first public release. If you want to compare it with the current React/Redux state of the art you can review how React components lifecycle looks like and how these components have to be linked to Redux in these infographics Sergio Gutiérrez designed in a previous blog post:

The lifecycle of a React component:

Android Jetpack Compose Review

Integration between any React component and Redux:

Android Jetpack Compose Review

If you compare it with the current state of the library, there are a lot of pull requests they still have to send before the first release. Maybe, in the future, we can see how they connect Jetpack Compose with libraries like kotlin-redux to be able to handle unidirectional data flows and Arrow for the lenses usage, recursion schemes, side effects, and simple data-types.

Additional notes to the state management:

After publishing this blog post the Jetpack Compose team contacted me to review this part of the content. They sent me a few notes about some parts of the post:

“This isn’t where we’d like people to go, but I can see how this could be easily misinterpreted. Will work on messaging here. We may often hear of “top-down data flow” or “unidirectional data flow” to describe this pattern, and the latter is probably the more accurate term. Composable functions can have local state. Data for a composable function (or “props” to use a React term) is provided to the composable via function parameters, but local state scoped to the composable can be introduced by leveraging Compose’s memoization capabilities. Right now in the repo we have a concept called “Effects” (which may be unifying with Composable functions in the future). You can use these to introduce local state now, either by creating an @Model state class and introducing it with memo, or by using any type and introducing it using state. For example:”

@Composable fun Counter() {
  // introduce a state value (of type `Int`, with initial value of `0`.
  // Note: the `+` syntax is temporary
  val count = +state { 0 }
  // use it to compose your UI. pass it into other composables as parameters
  Text(text="Count: ${count.value}")
  // modify the value inside of event handlers, for instance
  Button(text="Increment, onClick = { count.value += 1; })
}

“Alternatively, use the @Model and memo like I mentioned:”

@Model class CounterState(var count: Int)
@Composable fun Counter() {
  // introduce a CounterState value. Instance will be preserved across compositions.
  // Note: the `+` syntax is temporary
  val count = +memo { Counter(0) }
  // use it to compose your UI. pass it into other composables as parameters
  Text(text="Count: ${count.count}")
  // modify the value inside of event handlers, for instance
  Button(text="Increment, onClick = { count.count += 1; })
}

What about the performance?

Even when they talk about the implementation of a list of components, and they take into account the performance during the talk. They don’t go deep into the library implementation details. They describe the possible implementation of a ScrollingList but if you review the repository there is no such component implemented for now. They describe a promising component like this:

@Composable
fun NewsFeed(stories: LiveData<List<StoryData>>) {
    ScrollingList(stories.observe()) { story ->
        StoryWidget(story)
    }
}

However, this is not part of the repository right now and we will have to wait until a new release in order to check if the suggested implementation looks like this or not.

Also, related to the usage of Unit as return value has another important implication here. As the team is not designing the components API as a set of data we can manipulate easily, there is no way we can compare an already rendered view with a new version of this view with just a bunch of modified values in order to implement an efficient UI rendering from the outside. And this could be really important depending on the final implementation! If you review the React ecosystem, you’ll see how the usage of types for the Virtual DOM design let Facebook engineers implement a smooth UI thanks to the partial update of the device DOM using an efficient and fast diff algorithm. You can read about the Virtual DOM implementation here if you want.

I guess there is an inner mechanism inside the rendering code making all these components efficient when talking about drawing. However, I can’t talk about it because it wasn’t part of the talk and the code I’ve reviewed seems to use canvas API for the component’s rendering.

What if I don’t want to use Jetpack Compose?

Don’t you worry if you want to code like this, but you don’t have time to wait for the final release. You can always create custom views you can compose in your old school layouts and link them with the Jetpack Data Binding library. If you implement your custom view using a single rendering binding method and link the view with a single source of truth implemented using any Redux library you’ll get all the benefits. Don’t forget the layout and your custom views is something you can already compose easily. Keeping the state of the app as part of your model and implementing your custom views as a class with a render function will give you a similar result. Even if you don’t want to use custom views,  you can already do this with your view holders if you don’t follow the Google official guidelines and implement your RecyclerView’s view holder without exposing the internal views and with a method to render the data passed as a parameter. This solution is not based on a nice Kotlin DSL, but might be worthy for you.

Conclusions

The Android team is doing it great. Believe me when I say that this Compose API is way better than the current state of the art of Android development. If you don’t think so try to write a React/ReactNative/Vue application and you’ll better understand what using components like these will be in the future.

Keep in mind that even when this library will help us a lot in the future, the rest of the SDK will have to evolve similarly if we want to improve the way we write our apps. Apart from the design changes the Android Team will implement in the future in the Compose API,  there are a lot of points to enhance in the rest of the SDK: stop returning the execution of the libraries calls as part of the “onActivityResult” methods, let the users get an instance of an activity without initialising the activity lifecycle (really useful for testing), create a friendly API for the animated transitions, etc.

Last but not least, we think releasing a sneak peek like this of the source code, and the examples, is one of the best things Google did. This talk, documentation, and source code let them gather tons of feedback they use for future improvements. There are a lot of things to develop and I hope we will be able to use Compose in all our apps in the future.

References

Here you can find some useful resources about this topic:

Continue ReadingAndroid Jetpack Compose Review

End of content

No more pages to load