May 28, 2018 / Reading time: 6m

Jetpack series: 1 — androidx.*, a headache for a better package structure

jetpack

android

Getting that sweet com.androidx.* might not be as easy as one predicts.

1. Hello Google I/O

You can skip to part 3. if you are aware of this year’s Android announcements.

This year’s Google I/O was quite surprising for me, I was really happy to know that the whole android team is working hard every year to make our lives as developers of the green robot easier every year.

Last year we got the first iteration of the Architecture Components, the first step into tackling some of the biggest issues we’ve had forever, lifecycle, configuration changes, persistence etc.

This year the team doubled down and formed the Android Jetpack.

Jetpack is a set of libraries, tools and architectural guidance to help make it quick and easy to build great Android apps. It provides common infrastructure code so you can focus on what makes your app unique.

2. From support to eXtension!

Part of these changes was to unify the package structure of the android support libraries. If you’ve ever developed for android you are well aware of the whole mess that is the backwards-compatibility-libraries are: v4, v7, v13, v8, v?.

See for yourself: https://developer.android.com/topic/libraries/support-library/packages

Besides being confusing, this adds unneeded overhead to developers, why should we need to know if the backwards compatible Fragment class is present on the support-library-v4 or support-library-v7, and worse, some of these libraries already include another, and most mature projects just default to include all of them, even though we’re not exactly sure how much unnecessary stuff is being included (Javascript-much?), adding a library means more maintenance.


Don’t forget to check the project on GitHub: JoaquimLey/transport-eta

Baby steps into AndroidX

We could already see some modularisation happening, the libraries were being broken into smaller pieces (com.android.support:cardview-v7, com.android.support:recyclerview-v7, (…)) making our projects more lightweight, but still not the perfect setup.

Where is the recycler-view on the v7? v4? v13?

support-vN.* is dead, long live androidx.*

We’re not platform developers, so it makes sense to hide these small implementation details from the end-users, the developers, with the new package structure, we now clearer, unified, and explicit package naming:

"androidx.core:core-ktx:$versions.core_ktx"
"androidx.fragment:fragment:$versions.fragment"
"androidx.cardview:cardview:$versions.card_view"
"androidx.appcompat:appcompat:$versions.appcompat"

No more support-library version included in the artifact.

Clear separation:

android.* — bundled in the platformandroidx.* — extension library

Another very welcome change is the versioning system, each package has it own version, detached from the android API version, this way each extension library can be developed independently, I can imagine this helps the platform team to push more incremental updates, and more often.

Versioning changesThe new artefacts will follow Semantic Versioning, and will update independently, instead of all at once. Following this restructuring, it will be possible to update AndroidX libraries in your project independently. This avoids the problem of updating many Support Library modules in your project from e.g. 26.1.0 to 27.0.0 all at once.

3. Migrating your project

First things first, there’s already an “official” guide for this migration, this article is just me documenting my experience.


  • Download the canary version of Android Studio, you can keep both the sable and canary versions on your machine (this is necessary at the time of this writing)
  • Open your project on the canary version (AS-canary icon is yellow)
  • You can now go to the Refactor menu and select Refactor to AndroidX…

Ok now Android Studio will scan your project and change the legacy imports to the new androidx.* structure.

This is when things start to get 🐟. I’ve read some people getting their projects completely broken, imports not mapping correctly, and if you are unlucky, you have a lot of manual work to do.

For this project most of the changes went well, I had the odd androidx.app.Fragment in the code with the old support.v4.Fragment as the class import type of “errors”, but for the most part, these weren’t too hard to find, ofc it helps the code base is fairly young, on the other hand. If this wasn’t your case, you can find the library mappings here, godspeed sir!

Next step, which I’m not sure if AS should automatically do, was to change/add dependencies on the module’s build.gradle, in my case, since this a multi-module-project I keep a separate versions.gradle file where I have all the dependencies and versions centralised, this way I ensure all my modules are including the same version (this prevents some odd errors) and makes maintenance easier. So I had to add all the new androidx.* packages as well the new versioning.

And you said individual versioning is a good thing

The versioning was where I spent most of my time, I had set the correct versions, or was I? While following the Add Architecture Components cheat sheet. I was setting the old version into the new androidx structure. Ok this took me 2 minutes to write and 3 hours to figure out, I even filed an issue on the best practices with Android Jetpack googlesample project, but finally called it a night, frustration tunnels your vision.

— I left the issue open since, to my knowledge, there isn’t an actual google-provided template for this (on a mature with some actual ui project).

Next day, I found an androidx.* working project, for the slice component, that’s when I realised my rookie mistake. There it was, the solution, I could finally move along!

But no, gradle was still complaining, not finding any of the new libraries, I deleted my .gradle folder, I restarted AS invalidated caches, and nothing, nothing was working.

The errors were very ambiguous too, the install task was failing, but no specifics were given, after a lot of trial and error I decided to comment out all androidx.* and old libraries from the build script, re-sync, clean and make the project, this was to force a cold-cache refresh. With no more gradle errors (didn’t even looked at the code), I re-added the androidx libraries and Architecture Components, pushed sync and behold! Gradle was finally downloading the libraries!

Dagger, why do you hate me so much?

When I finally thought “this is it” it has to work now! Dagger2 started to break 😕, in the Android world, you never catch a break anyway. So I quickly went to the dagger2 repository and searched if any related issues had been opened.

searching androidx on dagger2’s repository

And luckily someone else had done this, and the solution was simple add the jetifier, this is mentioned in the official guide and I had wrongly removed from the gradle.properties file.

 (...)

# Android X: https://developer.android.com/topic/libraries/support-library/androidx-rn
android.enableJetifier=true
android.useAndroidX=true

I kept a link to the Androidx refactor documentation for future reference, and to give more context to other developers.

Updated dagger to latest version and re-sync the project. Finally got what I wanted, DaggerAppComponent import available.

OSS tip: Be a good citizen and search, before opening duplicates :)

At this point I’m crossing my fingers 🤞… And it finally compiled! Yes! The app is running.

Check the commit

Announcing androidx on android-developers.googleblog.com

You just read the first article of a series where I’m going to document my experience trying out the new components.

P.S: On that commit the only changes done was really the package structure, although I’ve included a lot of the new libraries there is no implementation at all. Also there are some repeated libraries (support) in other modules.

See also: Android Architecture Components: Now with 100% more MVVM

Share