Introduction
Android app development requires choosing appropriate tools and libraries to get a kick and run the application in a reasonable time schedule. As usual, the most time-consuming task is to research possible solutions and select the correct one. In this article, you’ll be able to find tools and libraries which are pretty popular among Android developers and pose as good choices for starting.
Kotlin coroutines
Coroutines are one of the best ways for asynchronous programming in Kotlin. The idea behind this is to make functions suspendable. It means that the function's execution can be hung at some point and returned later on. One of the advantages is that writing suspendable code with coroutines is nearly the same as writing synchronous code. Besides that, Kotlin’s coroutines are integrated with Android Jetpack’s View Models. These models provide a dedicated coroutine scope `viewModelScope` which is being canceled when the view model is cleared. Combining these two makes an asynchronous programming a piece of cake for developers.
The usage of Kotlin’s coroutines is as simple as visible in the example below:
suspend fun getUser(id: Int): User? { val response = webservice.getUser(id) return if (response.isSuccessful) { response.body() } else { // handle the error response } } viewModelScope.launch(Dispatchers.IO) { val user = getUser(id) }
Android Jetpack
Android Jetpack is designed by Google, containing all necessary components, and implements mechanisms that speed up the development process. Being continuously developed, Jetpack gains more and more components, like e.g. hilt - which provides a mechanism for dependency injection, compose - this is an alternative way for building an app’s UI. Examples presented above are being currently under development and released in alpha versions. However, there are some especially useful components already available in stable versions:
ViewModel
The ViewModel is designed for storing and managing data retrieved from HTTP API or database. That is an inherent element of MVVM architecture, remarkably popular among Android apps. The ViewModel class protects data from reloading when UI configuration changes. Hence, our API won’t be called for data when the user rotates the screen. The Android framework may also decide to slay or re-create a UI component in response to some user’s actions. ViewModel in the application prevents data from being loaded once again, thus app performance increases significantly.
The ViewModel is not the only mechanism for preventing the app data from configuration changes, however, it becomes a comfortable alternative for other solutions. Saving a UI state using ViewModel is much easier than e.g. overriding the `onSaveInstanceState()` method. The advantage of ViewModel is that it doesn’t require additional code and handling. The persistence logic is invisible from the developer’s perspective. Using the app state requires handling both saving and restoring that state in each activity and fragment. This means additional code and two more things to remember during development. Also, the instance state is not recommended for saving heavy objects and collections. That is the moment when we should use another persistence method, which means more code and room for potential bugs.
Navigation
The navigation component helps to handle the user’s journey paths in our apps. The set of introduced principles is especially useful to ensure that user experience is consistent, and predictable when going through the following screens. The Navigation uses an XML graph component that declares allowed paths for users. This component provides by default some features that are time-saving, e.g.: handling up to and back navigation correctly, standardized animations and transitions between screens, passing arguments between fragments in specific paths, scoping ViewModels, and sharing its data between multiple UI components. The Android Studio support here is also another advantage. Provides a Navigation Editor which makes graph creation as easy as just dragging and dropping specific actions.
Data Binding
Data Binding library saves developers from writing a bunch of boilerplate code. This library allows binding UI components in layouts with data sources using a declarative format, instead of programmatically. Data Binding replaces using the well-known method: findViewById() in Fragments and Activities, by just placing the assignment in XML layout file as shown in the example below:
The programmatic way:
findViewById<TextView>(R.id.example_text_view).apply { text = viewModel.exampleText }
The Data Binding way:
<TextView android:id=”@+id/example_text_view” android:text=”@{viewModel.exampleText}” />
The Data Binding supports also two-way assignments, so we are able to use with all kind of inputs or views. The only difference is that we need to add a “=” sign after the “@”, as below:
<EditText android:id=”@+id/example_edit_text” android:text=”@={viewModel.exampleText}” />
Retrofit + OkHttp
Nowadays the HTTP is the way that application networks in order to exchange data and media. Kotlin doesn’t provide a built-in module for networking, so Retrofit in combination with OkHttp becomes the most efficient way for consuming APIs. Retrofit requires declaring HTTP API endpoints as an interface, which is used to generate an API implementation service. The library provides a full range of HTTP methods, which are interface annotations, as shown in the example below:
interface UserService { @GET(“users/{id}”) suspend fun getUser(@Path(“id”) id: Int): Response<User> }
The builder class provided by Retrofit allows us to configure the service URL, as well as the converter factory for request, and response serialization, plus the HTTP client, which in our case is the OkHttp. OkHttp is the HTTP client that allows us to specify the requests interceptors, as well as connection timeouts like read, write, call, or connect timeouts. Also, OkHttp builder provides methods for setting custom protocols, connection pool, and other options, giving an opportunity to connect almost every service via HTTP.
Dagger
Unfortunately, Kotlin doesn’t provide a module for automated dependency injection in Android apps. This is the space for Dagger - an easy and flexible, fully static framework, which performs its work at compile time. Dagger creates and manages the graph of dependencies for our apps, saving a lot of boilerplate code and boost development. Proper Dagger configuration may become a challenge for developers doing it for the first time, however, it is still worth the effort. Accurately configured Dagger makes a dependency injection as easy as in Java, which basically means using just @Inject annotation. Of course, there are other tools available for dependency injection which are gaining popularity among developers. While Dagger has been around for a pretty long time already, that is still one of the most popular libraries which can be considered as a standard used for creating complex applications.
The basic example of providing and injecting dependencies:
@Module class UserModule { @Provides fun provideUser(): User { return User() } } class UserFragment { @Inject lateinit var user: User }
Combine to stay stable
There is no one perfect existing solution to solve all the obstacles when developing a steady app, but with a bit of help, good network skills, imagination, and a mix of available solutions you can deliver excellent results for your project and its users.