The Most Recent Features and Improvements in Android Jetpack

Kayvan Kaseb
Software Development
11 min readSep 14, 2022
The picture is provided by Unsplash

As you know, Android Jetpack is a set of libraries, tools, and guidance to help developers follow best-practices, diminish boilerplate code, and write code that works consistently over all Android versions and devices. Google has mentioned over 90% of the top 1000 apps use Jetpack. Therefore, nowadays, Jetpack plays a crucial role in modern Android development. In recent months, Google has announced some new features and enhancements for Android Jetpack, particularly at Google IO 2022. This article aims to discuss some new features and improvements in Jetpack for Android developers.

Introduction and Overview

Basically, Android Jetpack is a set of libraries, tools, and guidance to help developers follow best-practices, diminish boilerplate code, and write code that works consistently over all Android versions and devices. Thus, Jetpack can make it easier for Android developers to focus on the code they care about. Besides, most Android apps are already using Jetpack’s core libraries for primary functionality; however, adoption of optional libraries, such as Room and WorkManager, has continued to grow. Recently, Google has mentioned over 79% of the top 1000 apps relied on two or more non-core Jetpack libraries. In general, over 90% of the top 1000 apps use Jetpack. In fact, Google I/O 2022 announced some new features and improvements for Android Jetpack, which can be considered as three main area: 1. Architecture libraries 2. Performance optimization for Android apps 3. UI libraries. Thus, the following sections will consider some new features and enhancements in Android Jetpack .

Room

At Google I/O 2017, Room as an persistence library that offers an abstraction layer over SQLite to allow fluent database access, while controlling the full power of SQLite was introduced. Essentially, Room simplifies all the database-related operations, and makes them much more powerful because it allows the possibility of returning observables and compile-time checked SQL queries. Room 2.4 adds built-in support for enums and RxJava3. Room 2.4 also introduced QueryCallback class that provides a callback when SQLite statements are executed to simplify tasks like logging after execution. In addition, Room 2.4 has graduated support for Kotlin Symbol Processing(KSP) to stable, including support for Kotlin 1.6.

Kotlin Symbol Processing (KSP) is an API that you can use to develop lightweight compiler plugins. KSP provides a simplified compiler plugin API that leverages the power of Kotlin while keeping the learning curve at a minimum. Compared to kapt, annotation processors that use KSP can run up to 2 times faster.

KSP is a replacement for KAPT that processes annotations natively in the Kotlin compiler, and can notably decrease build times. KSP tries to bridge the gap between writing compiler plug-ins and maintainability. It can be seen as a layer for protecting your code generator from compiler API modifications. That also means some functionality of compiler plug-ins could not be accessible. KSP is Kotlin First. This means it identifies Kotlin syntax, and makes it faster because it does not rely on extracting Java entities. Room 2.5.0 contains the initial stages of a full Kotlin rewrite. It remains binary compatible with the previous Java sourced version, but this change sets the foundation for future Kotlin-related enhancements. Google has also introduced built-in support for Paging 3.0 with the Room-paging artifact. As a result, this allows Room queries return PagingSource objects. As you know, the central Paging library component in the repository layer is PagingSource. Every PagingSource object specifies a source of data, as well as the way for retrieving data from that source. So, this object can load data from any single source, such as network sources and local databases. Moreover, Room has supported relational query methods using multi-map, nested map, and array return types. This allows Android developers to do JOIN queries easily without defining other data structures. Initially, some queries probably need access to multiple tables to calculate the output. You can have an opportunity to use JOIN clauses in your SQL queries to reference more than one table.

In Room 2.4 and higher, you can also query columns from multiple tables without defining an additional data class by writing query methods that return a multimap.

For instance, you can be able to return a mapping of User and Book directly from your query method instead of returning a list of instances of a custom data class, which keeps pairings of User and Book instances:

@Query(
"SELECT * FROM user" +
"JOIN book ON user.id = book.user_id"
)
fun loadUserAndBookNames(): Map<User, List<Book>>

Lastly, to perform database migrations between two databases, Room has added additional properties and annotations to simplify the task for developers. A new AutoMigration property on the @Database annotation can be applied to mention which versions to auto migrate to and from. Additionally, it declares when Room requires additional information regarding table and column modifications, the @AutoMigration annotation can be used to specify the inputs. For instance:

@Database(
version = MusicDatabase.LATEST_VERSION,
entities = [
Song.class,
Artist.class
],
autoMigrations = [
@AutoMigration (
from = 1,
to = 2
),
@AutoMigration (
from = 2,
to = 3,
spec = MusicDatabase.MyExampleAutoMigration::class
)
],
exportSchema = true
)
abstract class MusicDatabase : RoomDatabase() {
const val LATEST_VERSION = 3

@DeleteTable(deletedTableName = "Album")
@RenameTable(fromTableName = "Singer", toTableName = "Artist")
@RenameColumn(
tableName = "Song",
fromColumnName = "songName",
toColumnName = "songTitle"
)
@DeleteColumn(fromTableName = "Song", deletedColumnName = "genre")
class MyExampleAutoMigration : AutoMigrationSpec {
@Override
override fun onPostMigrate(db: SupportSQLiteDatabase) {
//....
}
}
}

Even though Room provides both automated and manual ways for incremental migration, automatic migrations work for most basic schema modifications. Therefore, you probably require to declare migration paths manually for more complicated changes and situations.

Paging

In fact, the Paging library helps developers load and show pages of data gradually and gracefully from a larger dataset from local storage or over network. This approach supports your Android app to utilize both network bandwidth and system resources more effectively in reality.

Using Paging library in Android app architecture, the picture is provided by Google documents

Paging 3 is remarkably different from previous versions of the Paging library. This version offers improved functionality and addresses typical issues with using Paging 2. For example:

  1. First-class support for Kotlin coroutines and Flow.
  2. Built-in load state and error signals for responsive UI design
  3. Enhancements for the repository layer, like cancellation support.
  4. Enhancements for the presentation layer, such as custom page transforms and loading state headers/footers.

Nevertheless, Paging 3.1 brings stable support for Rx and Guava integrations, which provide Java alternatives to Paging’s native use of Kotlin coroutines. The library has also enhanced managing of invalidation race conditions with a new return type, LoadResult.Invalid, to display invalid or stale data.

PagingSource.LoadResult.Invalid has been added as a new return type from PagingSource.load, which causes Paging to discard any pending or future load requests to this PagingSource and invalidate it. This return type is designed to handle potentially invalid or stale data that can be returned from the database or network.

Furthermore, this version has improved handling no-offloads and operations on empty pages by recommending the new APIs as follows: .onPagesPresented and .addOnPagesUpdatedListener.

Navigation

Android Jetpack’s Navigation component helps you built navigation, from simple button clicks to more complex patterns, such as app bars and the navigation drawer. The recent versions have had some considerable improvements. First, the new Navigation Compose artifact provides integration between the navigation component and Jetpack compose. It uses composable functions as the destinations in your app. Second, supporting for Multiple Back Stacks has been easier for developers, without any code changes. Navigation UI now automatically saves and restores the state of pop destinations. Third, large screen support has also enhanced. The navigation-fragment artifact now includes a prebuilt implementation of a two pane layout via the new AbstractListDetailFragment. This fragment uses a SlidingPaneLayout to manage a List Pane (handled by your subclass) and a Detail Pane, which uses a NavHostFragment as its implementation.

SlidingPaneLayout provides a horizontal, multi-pane layout for use at the top level of a UI. A left (or start) pane is treated as a content list or browser, subordinate to a primary detail view for displaying content.

Finally, all navigation artifacts have been rewritten in Kotlin. This has enhanced nullability of classes applying generics, like Nav type subclasses with more usability improvements to come.

DataStore

Jetpack DataStore is an advanced and enhanced data storage solution for replacing SharedPreferences, as it is thread-safe and non-blocking. In general, DataStore is a Jetpack library that provides a safe and consistent method to store small amounts of data, like preferences or Android app state. DataStore is built based on Kotlin coroutines and Flow to store data asynchronously and consistently.

In coroutines, a flow is a type that can emit multiple values sequentially, as opposed to suspend functions that return only a single value. For example, you can use a flow to receive live updates from a database.

Although SharedPreferences works well for smaller apps, DataStore can support type safety, asynchronous operations, and error handling, as well as a number of helpful features, like data migration. Migrating from SharedPreferences to DataStore is a simple process.

Note: This migration only supports the basic SharedPreferences types: boolean, float, int, long, string and string set. If the result of getAll contains other types, they will be ignored.

JankStats

The advanced JankStats library helps you track and analyze problematic performance issues in your Android app’s UI, like reports on dropped rendering frames. JankStats builds on top of existing Android platform APIs, including FrameMetrics API, but can be used back to API level 16.

There are a number of problems that can create an inappropriate performance in an application. One of the most important situations to look out for in your Android application is Jank indeed. Jank happens when your app is exceedingly busy with performing some tasks on the main thread and misses the timing window to draw a frame on screen. Even though Jank can happen when scrolling, you can observe it in other cases, like when animating between scenes or transitioning from one window to another.

Additionally, the JankStats library can provide some extra capabilities, such as internal heuristics for identifying Jank, offering a mechanism to help track the current state of the UI and user, and reporting callbacks to upload data for analysis.

Baseline Profiles

Startup time is a critical component to improve user engagement with your application. Increasing the speed and responsiveness of an app leads to more daily active users and a higher average return visit rate.

One of the most effective ways to boost performance is implementing Baseline Profiles into your app or library. In general, it can remarkably optimize Android app startup time, decrease slow rendering, and enhance performance for end users. Obviously, application speed can have a substantial impact on a user’s experience, specially when using apps right after installation. So, Baseline Profiles allow apps and libraries to support the Android run-time with metadata about code path usage that it utilizes to prioritize ahead-of-time compilation. This profile data is aggregated over libraries and lands in an app’s APK as a baseline.prof file. Afterwards, it is applied at install time to partially pre-compile the app and its statically-linked library code. You should make sure that the you measure the performance of Baseline Profiles using a physical device running Android 7 or higher. Hence, this can be useful for making apps faster and diminish dropped frames when a user interacts with an app at the first time.

Baseline Profiles are a list of classes and methods included in an APK used by Android Runtime (ART) during installation to pre-compile critical paths to machine code. This is a form of profile guided optimization (PGO) that lets apps optimize startup, reduce jank, and improve performance for end users.

Google has added Baseline to other popular libraries, such as Fragments and Compose. However, if you want to build your own Baseline Profile, you will require to use the Macrobenchmark library.

Macrobenchmark

Basically, benchmarking is an efficient method to inspect and monitor the performance of your Android app. You can regularly run benchmarks to help analyze, trace, and debug performance problems.

The Macrobenchmark library injects events and monitors results externally from a test application that is built with your tests. Therefore, when writing the benchmarks, you don’t call your application code directly and instead navigate within your application as a user would.

For Android developers in favor of understanding their app’s performance, the Macrobenchmark library helps developers better understand app performance by extending Jetpack’s benchmarking coverage to more complicated situations, like scrolling a RecyclerView, or running animations. This provides the capability to capture traces and measure trace sections. Furthermore, this library could be used remotely to trace metrics in continuous integration testing or locally with profile results viewable from Android Studio.

Recent updates and changes of this library have considerably improved testing speed and added several new experimental features. For instance:

  1. AudioUnderrunMetric has been added into Macrobenchmark library under experimental flag to allow detection of audio underruns.
  2. @BaselineProfileRule to automatically generate Baseline profiles for a given critical user journey has been added.
  3. CompilationMode.Partial to measure the effectiveness of Baseline Profiles.

WorkManager

The WorkManager library is an Android’s recommended way to schedule deferrable and asynchronous tasks that run even if the app exits or the device restarts. In other words, WorkManager has been designed for work, which is needed to run reliably even if the user navigates off a screen, the app exits, or the device restarts. Since most background processing is best accomplished through persistent work, WorkManager is the most important recommended API for background processing. As a matter of fact, WorkManager can manage three main kinds of persistent work: Immediate, Long Running, and Deferrable.

Different kinds of Types of persistent work, the picture is provided by Google documents

Some new features and enhancements from the latest versions of WorkManager can be mentioned as follows:

  1. Reducing multi-process SQLite contention when initializing WorkManager.
  2. Introducing a new WorkRequest.Builder.setExpedited(...) API to help with Foreground Service restrictions in Android 12.
  3. Providing an ability to update WorkRequests in a non-intrusive, and preserving original enqueue time or chaining.

WindowManager

People use your apps on all kinds of devices. Unlock the full potential of your apps by using responsive layouts that adapt to fit phones, tablets, foldables, and Chrome OS devices.

The Jetpack WindowManager library enables Android developers to support new device form factors and multi-window environments. The library offers a typical API surface for API versions 14 and above. The first release targets foldable devices, but future versions will extend to support more display types and window features. The recent versions of WorkManager has introduced some new features as follows:

  1. Adding support for folding phones through WindowInfoTracker.
  2. Adding methods to calculate the current and maximum WindowMetrics.
  3. Expanding on the experimental ActivityEmbedding API.
  4. Supporting test APIs.

Compose

Jetpack Compose is an Android’s modern toolkit for building native UI. It makes easier and accelerates UI development on Android to create more robust and responsive UIs. Google has mentioned that over 100 of the top 1000 apps in the Play Store are now using Compose. In addition, Jetpack Compose is built based on composable functions. These functions enable you to define your app’s UI programmatically by expressing how it should look and providing data dependencies, instead of focusing on the process of the UI’s creation. Compose 1.2 beta introduced many new features and improvements. For instance:

  1. One of the top-voted bugs has been addressed by making includeFontPadding a customizable parameter.
  2. Announcing downloadable fonts in Compose: You can use the new APIs for Compose to access Google Fonts asynchronously.
  3. Supporting Text Magnifier
  4. Evolving Lazy Layouts by adding new grid APIs LazyVerticalGrid and LazyHorizontalGrid as well as new experimental API, called LazyLayout.
  5. Bringing new features for Compose development(beta version) via Android Studio Dolphin.
  6. Moving Compose for Wear OS to Beta
  7. Interoping with CoordinatorLayout

In Conclusion

Recently, Jetpack plays a vital role in modern Android development. Google has mentioned over 90% of the top 1000 apps use Jetpack. Google has announced some new features and improvements for Android Jetpack in recent months, specially at Google IO 2022. This article considered some advanced features and enhancements in Jetpack for Android developers based on Google documents and resources.

--

--

Kayvan Kaseb
Software Development

Senior Android Developer, Technical Writer, Researcher, Artist, Founder of PURE SOFTWARE YAZILIM LİMİTED ŞİRKETİ https://www.linkedin.com/in/kayvan-kaseb