Jetpack Compose What and Why, 6 questions

1. The background and original intention of the emergence of this technology, and what kind of goals or problems to be solved.

What is Jetpack Compose? It is a declarative UI Toolkit for Android.

Its main purpose is to change the way UI is written imperatively to declarative.

imperative

Android was previously written as imperative: View Hierarchy is a tree of UI widgets that needs to be updated when the state of the app changes. The usual approach is to find the node to update by findViewById(), and update the internal state of the control by setText(), addChild(), setImageBitmap(), and so on. Each control has its own internal state and exposes getters/setters, allowing program logic to interact with the control.

Why imperative is bad:

  • Manually updating the view in this way increases the chance of making mistakes. If a piece of data is rendered in more than one place, you might forget to update one of the views.
  • It is easy to create illegal states, such as two updates that conflict in an unexpected way (for example, one to update a value and the other to remove a node).
  • The complexity of maintenance increases with the number of views that need updating.

declarative

So, over the past few years, the industry has been exploring and moving toward a declarative UI model. The goal is to simplify building and updating the UI.

Jetpack Compose is a declarative UI framework. The technique works by rebuilding the entire screen from scratch and then applying only the necessary changes. This approach avoids the complexity of manually updating stateful View.

In Compose’s declarative solution, widgets are relatively stateless and do not expose getters/setters. In fact, widgets are not exposed as objects at all. The Composable method is actually called with different parameters when the UI is updated. The Composable converts the current application state into the UI when data changes.

2. What are the advantages and disadvantages of this technology, or what are the trade-offs of this technology?

Compose’s advantages:

  • Now that Google has invested a lot of resources (learning resources, community challenges, IDE and compiler support, desktop versions, etc.) into making Compose the standard for Android UI development in the future, we have reason to believe that Google will continue to do so.
  • Compose’s declarative writing method is compatible with Flutter, SwiftUI, and React, which is conducive to the unity of architectural ideas in teams that support multiple platforms.
  • Declarative UI is faster to write and less error-prone.
  • Because all of the code is written by Kotlin (really 100% Kotlin) and takes advantage of Kotlin’s strong type safety, the compiler prompts a lot of errors.
  • Fixed and updated some old apis: (Buggy Android Views: Picker, Spinner, EditText, with some Edge cases. Since it’s always hard to change an old one, create a new one.)
  • Composable is more flexible and reusable than inheritance-based View architecture. For example, multiple sources can be reused by composition instead of being limited by a single inheritance.

Take Button as an example. In traditional UI, it is a single inheritance class: Button -> TextView -> View. In Compose’s world, it’s just a @composable method that contains other Composables, surfaces, rows, etc. For example, list->detail can be used to achieve composable reuse of the two interfaces by extracting method parameters.

  • Supports intercalling with view-based UI systems. This has two advantages: it is conducive to the mixed use and gradual migration of existing project APPS; A traditional View can be used as a secondary option when Compose cannot meet its requirements.
  • Works well with other libraries in the Jetpack family (ViewModel, Kotlin Flow, Coroutines, Paging, Hilt, Navigation…).

Disadvantage:

  • You need to use the Canary version of Android Studio, and currently (2021.5) the IDE has some issues.
  • Gradle will also be updated to the latest version (7.0.0-Alpha15), which is not very stable and has some problems.
  • Compose Alpha is currently in beta, and the latest Google I/0 release says a stable version will be available in July.
  • -> But Google has put a lot of resources into promoting it, and community support is growing fast.
  • Although Google has packaged material’s compose library, there are still some View controls that cannot be provided, such as WebView, MapView, etc.

3. Scenarios in which this technology is used.

For Example, Jetpack Compose uses a new way of writing UI for Android View hierarchy instead of using XML, instantiating a View object in code and adding it to the View Hierarchy. Soon to be standard for Google Android.

Note that the change here is not only a change in UI writing, but also a change in state management thinking. Declarative, one-way data flow, single data source. The internal model of Android in recent years has been nothing but separation of data and View, ignorance and automatic update of View, clear logical management and separation, testability and so on.

With the exception of the ViewModel layer, which is strongly associated with the View, other business logic, data interaction, etc., are not affected, so even if the app decides to gradually migrate to Compose, it will only handle the View drawing and the layer adjacent to the View.

4. Components and key points of technology.

Jetpack Compose’s general features:

  • Declarative UI.f(state)=UI.
  • Built on Kotlin.
  • Unbundled: not bundled with systems, but like libraries in Jetpack, version bundled, with maintenance releases for updates and consistency across systems.
  • Built for Interop. Can intercall existing views, suitable for gradual migration of existing projects.
  • Built-in controls and Theming, support material Design.

Composable functions

Compose defines a series of composable functions that receive data and emit UI elements.

@Composable
fun Greeting(names: String) {
    Text("Hello $name")
}
Copy the code

Composable method features:

  • All methods must be present@ComposableAnnotation.
  • Method parameters are data.
  • Emit UI elements by calling other Composable methods.
  • Methods do not return values because they are describing screen state, not building UI widgets.
  • Methods should be fast, idempotent, and side-effect free. This requires that methods do not modify external attributes or global variables, nor do Random calls, etc.

One small difference is that unlike the normal Kotlin method naming convention, the composable method names are capitalized because it represents a widget.

Recomposition

The Compose framework wisely picks out the parts that have changed and need to be redrawn.

In Compose, if the Composable function is called and new data is passed in, the method is recomposed: the widgets emitted by this method are redrawn as needed.

Since redrawing the entire UI tree will cost a lot, the Composable function will be redrawn only when the input changes. Methods and lambdas with unchanged parameters will be skipped to improve the efficiency of recompose.

Therefore, never rely on performing side-effects of the Composable function as recomposition may be skipped.

Side effects including:

  • Update the shared object.
  • Update the Observable in the ViewModel.
  • Update Shared preferences.

Since the Composable functions are likely to be executed frame by frame (such as during animation), it should be fast enough to consider a background coroutine if time-consuming operations are required.

5. Underlying principles and key implementation of the technology.

Compose has several features:

  • Composable functions can be executed in any order.
  • Composable Functions can execute in parallel.
  • Recomposition will skip as many composable functions as possible. If side-effects are really needed, consider callback.
  • Recomposition is optimistic that there will be no new state changes during this redraw, and if there are new state changes, it may cancel the current draw and start again with new parameters.
  • The Composable function is likely to be executed frequently (e.g. animations), so avoid time-consuming operations.

There is no official documentation or architecture for Compose’s underlying principles. Because everyone is probably still learning how to use it, the underlying implementation details of this technology haven’t been discussed in great detail. There is one problem: stackoverflow.com/questions/5…

Composable uses the Composable annotation @composable but does not add an annotation handler (Kapt) so it does not rely on annotations to generate code at compile time.

To add dependencies, you need to build. Gradle:

    composeOptions {
        kotlinCompilerExtensionVersion compose_version
    }
Copy the code

So it has something to do with Kotlin’s compiler.

This video: Understanding Compose (Android Dev Summit ’19) starts at 17:18.

@composable is more like a language key. An analogy to suspend has several things in common:

  • Changed the type of method.
  • The calling context of a method is enforced.

Part of the update

With the customized Kotlin compiler plug-in, methods of the composable affected by the data are re-invoked when the data changes.

6. Existing implementations and comparisons.

Android View vs. Jetpack Compose

Android View and Jetpack Compose are similar:

  • It’s all Android UI.

Where Jetpack Compose improves the View system:

  • You no longer need to worry about deep nesting. The Compose UI does not allow for multi-pass measurement, improving efficiency.

A comparison of Flutter and Jetpack Compose.

Jetpack Compose and Flutter are similar:

  • Declarative UI,UI = f(state).
  • Both have Web and desktop versions.
  • There are some material controls and resources provided by the authorities. For example, all scaffolds provide scaffolding.
  • Both can be mixed with native, though not to the same degree. For Compose, the mix is a bit more granular.
  • You can preview the UI as you change it.

What Jetpack Compose does better than Flutter:

  • Based on Kotlin, the Flutter dart is friendlier to Android developers than the Flutter DART.
  • Coming up to the last point, because Compose only changed the UI, the rest of the code base is still the Android native code logic, and there are more third-party libraries available. Flutter, on the other hand, uses other packages to do JSON parsing, databases, etc.
  • The stateateful widget of Flutter had to be setState, which was not very convenient and error prone.
  • Jetpack Compose’s Recomposition looks smarter and fully automatic, unlike Flutter, which requires developers to set up flags to indicate which parts don’t need to be redrawn.
  • Installation package size should be advantageous? Because the Flutter SDK includes its own graphics engine, Compose has no native layer.

What makes Flutter better than Jetpack Compose:

  • Flutter also supports iOS.
  • Flutter is a little more mature than Jetpack Compose and has been verified by some apps.
  • Flutter has its own graphics engine, Skia, which makes drawing more efficient. (No verification, pure guess)

Reference

  • Thinking in Compose
  • Using Jetpack libraries in Compose | Session – > the state management and other Jetpack library combining with the video is great.