Skip to content

13. Conclusion

We wrote the native client [Android] for the application [RdvMedecins], in [Kotlin] and [Jetpack Compose]. For the user, it offers the same screens as the HTML application from course [NestJS], as well as the [Vue.js], [Angular] and [React], and the client [Flutter].

The server, however, has not changed. Its API and JSON—whose contract (routes, bodies, codes, and error keys) was sufficient to write the client without ever reading its code—serves both a browser and a phone indiscriminately. There is only one difference: on the phone, there is no browser to store the token cookie, so the client HTTP ([OkHttp] and its [CookieJar]) took on this role in just a few lines of code. Security remains unchanged: it is still the server that authenticates users, verifies roles and rules, and validates forms.

Readers who have taken the [Flutter] course can compare:

  • both are based on the same idea: the interface is a function of the state. A [Flutter] widget has a [build()] method that returns a widget tree; a [@Composable] function CALLS other [@Composable] functions. When the state changes ([setState] / the assignment of a [mutableStateOf]), the interface is recalculated; [Compose] re-executes only the functions that read the modified state;
  • [Flutter] draws each pixel itself, using its own engine, on all platforms; [Compose] is the interface toolkit for [Android] itself: the application is more lightweight, integrates naturally with the system (theme, language, accessibility, password manager), and has direct access to all the API components of [Android]. On the other hand, it runs only on [Android] ([Compose Multiplatform], from [JetBrains], also supports iPhone, the desktop, and the web);
  • [Kotlin] and [Dart] are two very similar, typed, compiled languages with non-nullable types. [Kotlin] introduces the [data] classes (and their [copy]), the interfaces [sealed] and the exhaustive [when], extensions, coroutines, and serialization written at compile time;
  • on [Android], the activity is RECREATED whenever the configuration changes (rotation, language): consider what needs to be preserved ([rememberSaveable], [ViewModel], the navigation path);
  • The [Jetpack] ecosystem provides, through official repositories, what [Flutter] requires from packages: navigation, [ViewModel], [DataStore], and testing.

The concepts covered in this course ([@Composable] functions, state and recomposition, effects and lifecycle, [CompositionLocal], [ViewModel], and [StateFlow], coroutines and [Flow], navigation and guards, forms, resources, and languages) are those found in any modern [Android] application. To learn more:

  • the official documentation, developer.android.com/compose, its training courses (“Android Basics with Compose”), and its architecture guide;
  • dependency injection with [Hilt] (rather than the [Application] and [LocalDependencies] objects);
  • [Retrofit], which generates the access layer for API from a simple annotated interface ([@GET("doctors")]);
  • the tests: unit tests (the reducer from Example 06, the rules from Example 07), and the instrumented tests for [Compose] that run the application on an emulator (the screenshots in this document were taken using these tests; see appendices);
  • [Room], the local database, for an application that runs offline;
  • [Compose Multiplatform], for reusing this code on iPhone and the desktop.