11 May 2022
Posted by Amanda Alexander, Product Manager, Android
Android Jetpack is a key pillar of Modern Android Development. It is a suite of over 100 libraries, tools and guidance to help developers follow best practices, reduce boilerplate code, and write code that works consistently across Android versions and devices so that you can focus on building unique features for your app.
Most apps in Google Play use Jetpack for app architecture. Today, over 90% of the top 1000 apps use Jetpack.
Here are the highlights of recent updates in Jetpack - an extended version of our What’s New in Jetpack talk for I/O!
Below we’ll cover updates in three major areas of Jetpack:
And then conclude with some additional key updates.
App architecture libraries and components ensure that apps are robust, testable, and maintainable.
Room is the recommended data persistence layer which provides an abstraction layer over SQLite, allowing for increased usability and safety over the platform.
In Room 2.4, support for Kotlin Symbol Processing (KSP) moved to stable. KSP showed a 2x speed improvement over KAPT in our benchmarks of Kotlin code. Room 2.4 also adds built-in support for enums and RxJava3 and fully supports Kotlin 1.6.
Room 2.5 includes the beginning of a full Kotlin rewrite. This change sets the foundation for future Kotlin-related improvements while still being binary compatible with the previous version written in the Java programming language. There is also built-in support for Paging 3.0 via the room-paging artifact which allows Room queries to return PagingSource objects. Additionally, developers can now perform JOIN queries without the need to define additional data structures since Room now supports relational query methods using multimap (nested map and array) return types.
@Query("SELECT * FROM Artist JOIN Song ON Artist.artistName = Song.songArtistName") fun getArtistToSongs(): Map<Artist, List<Song>>
Relational query methods using multimap return types
Database migrations are now simplified with updates to AutoMigrations, with added support for additional annotations and properties. A new AutoMigration property on the @Database annotation can be used to declare which versions to auto migrate to and from. And when Room needs additional information regarding table and column modifications, the @AutoMigration annotation can be used to specify the inputs.
Database( version = MyDb.LATEST_VERSION, autoMigrations = { @AutoMigration(from = 1, to = 2, spec = MyDb.MyMigration.class), @AutoMigration(from = 2, to = 3) } ) public abstract class MyDb extends RoomDatabase { ...
The DataStore library is a robust data storage solution that addresses issues with SharedPreferences. To better understand how to use this powerful replacement for many SharedPreferences use cases, you can check out a series of videos and articles in Modern Android Development Skills: DataStore which includes guidance on testing your app’s usage of the library, using it with dependency injection, and migrating from SharedPreference to Proto DataStore.
The Paging library allows you to load and display small chunks of data to improve network and system resource consumption. App data can be loaded gradually and gracefully within RecyclerViews or Compose lazy lists.
Paging 3.1 provides stable support for Rx and Guava integrations, which provide Java alternatives to Paging’s native use of Kotlin coroutines. This version also has improved handling of invalidation race conditions with a new return type, LoadResult.Invalid, to represent invalid or stale data. There is also improved handling of no-op loads and operations on empty pages with the new onPagesPresented and addOnPagesUpdatedListener APIs.
To learn more about Paging 3, check out the new, simplified Paging Basics Codelab on the Android Developer site which demonstrates how to integrate the Paging library into an app that shows a list.
The Navigation library is a framework for moving between destinations in an app.
The Navigation component is now integrated into Jetpack Compose via the new navigation-compose artifact which allows for composable functions to be used as destinations in your app.
The Multiple Back Stacks feature has improved to make it easier to remember state. NavigationUI now automatically saves and restores the state of popped destinations, meaning developers can support multiple back stacks without any code changes.
Large screen support was enhanced with the navigation-fragment artifact providing a prebuilt implementation of a two-pane layout in AbstractListDetailFragment. This fragment uses a SlidingPaneLayout to manage a list pane – managed by your subclass – and a detail pane, which uses a NavHostFragment.
All Navigation artifacts have been rewritten in Kotlin and feature improved nullability of classes using generics – such as NavType subclasses.
To learn more about how our key architecture libraries work together, you can view a collection of videos and articles covering best practices for modern Android development in a series called Modern Android Development Skills: Architecture.
Using performance libraries allows you to build performant apps and identify optimizations to maintain high performance, resulting in better end-user experiences.
App speed can have a big impact on a user’s experience, particularly when using apps right after installation. To improve that first time experience, we created Baseline Profiles. Baseline Profiles allow apps and libraries to provide the Android run-time with metadata about code path usage, which it uses to prioritize ahead-of-time compilation. This profile data is aggregated across libraries and lands in an app’s APK as a baseline.prof file, which is then used at install time to partially pre-compile the app and its statically-linked library code. This can make your apps load faster and reduce dropped frames the first time a user interacts with an app.
We’ve already started leveraging Baseline Profiles at Google. The Play Store app saw a decrease in initial page rendering time on its search results page of 40% after adopting Baseline Profiles. Baseline profiles have also been added to popular libraries, such as Fragments and Compose, to help provide a better end-user experience. To create your own baseline profile, you need to use the Macrobenchmark library.
The Macrobenchmark library helps developers better understand app performance by extending Jetpack’s benchmarking coverage to more complex use-cases, including app startup and integrated UI operations such as scrolling a RecyclerView or running animations. Macrobenchmark can also be used to generate Baseline Profiles.
Macrobenchmark has been updated to increase testing speed and has several new experimental features. It also now supports Custom trace-based timing measurements using TraceSectionMetric, which allows developers to benchmark specific sections of code. Additionally, the AudioUnderrunMetric now enables detection of audio buffer underruns to help understand audible jank.
BaselineProfileRule generates profiles to help with runtime optimizations. BaselineProfileRule works similarly to other macro benchmarks, where you represent user actions as code within lambdas. In the example below, the critical user journey that the compiler should optimize ahead of time is a cold start: opening the app’s landing activity from the launcher.
@ExperimentalBaselineProfilesApi @RunWith(AndroidJUnit4::class) class BaselineProfileGenerator { @get:Rule val baselineProfileRule = BaselineProfileRule() @Test fun startup() = baselineProfileRule.collectBaselineProfile( packageName = "com.example.app" ) { pressHome() // This block defines the app's critical user journey. Here we are // interested in optimizing for app startup, but you can also navigate // and scroll through your most important UI. startActivityAndWait() } }
For more details and a full guide on generating and using baseline profiles with Macrobenchmark, check our guidance on the Android Developers site.
The new JankStats library helps you track and analyze performance problems in your app’s UI, including reports on dropped rendering frames – commonly referred to as “jank.” JankStats builds on top of existing Android platform APIs, such as FrameMetrics, but can be used back to API level 16.
The library also offers additional capabilities beyond those built into the platform: heuristics that help pinpoint causes of dropped frames, UI state that provides additional context in reports, and reporting callbacks that can be used to upload data for analysis.
Here’s a closer look at the three major aspects of JankStats:
The Tracing library enables profiling of app performance by writing trace events to the system buffer. Tracing 1.1 supports profiling in non-debug builds back to API level 14, similar to the <profileable> manifest tag which was added in API level 29.
Several changes have been made to our UI libraries to provide better support for large-screen compatibility, foldables, and emojis.
Jetpack Compose, Android’s modern toolkit for building native UI, has reached 1.2 beta today which has added several features to support more advanced use cases, including support for downloadable fonts, lazy layouts, and nested scrolling interoperability. Check out the What’s New in Jetpack Compose blog post to learn more.
The new WindowManager library helps developers adapt their apps to support multi-window environments and new device form factors by providing a common API surface with support back to API level 14.
The initial release targets foldable device use cases, including querying physical properties that affect how content should be displayed.
Jetpack’s SlidingPaneLayout component has been updated to use WindowManager’s smart layout APIs to avoid placing content in occluded areas, such as across a physical hinge.
The new DragAndDrop library also helps with new form factors and windowing modes by enabling developers to accept drag-and-drop data – both from inside and outside their app. DrapAndDrop includes a consistent drop target affordance and it supports back to API level 24.
The AppCompat library allows access to new APIs on older API versions of the platform, including backports of UI features such as dark mode.
AppCompat 1.4 integrates the Emoji2 library to bring default support for new emoji to all text-based views supported by AppCompat on API level 14 and above.
Custom locale selection is now supported back to API level 14. This feature enables manual persistence of locale settings across app starts, and supports automatic persistence via a service metadata flag. This tells the library to load the locales synchronously and recreate any running Activity as needed. On API level 33 and above, persistence is managed by the platform with no additional overhead.
The Annotation library exposes metadata that helps tools and other developers understand your app's code. It provides familiar annotations like @NonNull that pair with lint checks to improve the correctness and usability of your code.
Annotation is migrating to Kotlin, so now developers using Kotlin will see more appropriate annotation targets, including @file.
Several highly-requested annotations have been added with corresponding lint checks. This includes annotations concerning method or function overrides, and the @DeprecatedSinceApi annotation which provides a corollary to @RequiresApi and discourages use beyond a certain API level.
We now have over 100 projects in our GitHub! Several modules are open for developer contributions using the standard GitHub-based workflow:
Check the landing page for more information on how we handle pull requests, and to get started building with Jetpack libraries.
This was a brief tour of all the changes in Jetpack over the past few months. For more details on each Jetpack library, check out the AndroidX release notes, quickly find relevant libraries with the API picker and watch the Google I/O talks for additional highlights.
Java is a trademark or registered trademark of Oracle and/or its affiliates.