Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.Sign up
Turbolinks Android Adapter 1.x Deprecation
Following a breaking change in Chrome 64, this Turbolinks 1.x adapter for Android hit an architectural dead end. Existing projects built with this version of the adapter will continue to work, although there may be some slow memory leaks and other minor issues.
Still, the general architecture and approach continues to work well enough to power the Basecamp 3 Android application. We run a forked version that bypasses the breaking change in Chrome 64 (but at the same time creates a different set of UI challenges with native dialogs). We considered releasing this slightly modified version, but eventually realized this modified library carried too many of its own drawbacks. In the end we felt that it would only cause confusion to release a version that didn't fix the root issue and simply presented a different set of issues.
So to that end, we're currently working on a brand new Turbolinks 2.0 adapter for Android that will solve the root cause of the Chrome 64 breaking change and get us in line with the latest architectural guidelines from Google.
We don't have this new adapter ready just yet, though. It's under active development, and we'll share the code as soon as we have something solid that we'd build our own future applications upon. But until that point, we're stuck in a bit of a transition period. The old Turbolinks adapter can do the job for existing applications that were built on it, but it's hard for us to recommend that new applications be started on an older architectural model when Google is actively recommending a new, single-activity approach.
So at this time you should probably just build a vanilla WebView application that follows the single-activity approach without Turbolinks for Android. And then when we have a Turbolinks adapter that's compatible ready, you can upgrade to use that.
We will not be maintaining this adapter any further beyond whatever emergency fixes we might need for Basecamp 3's own usage.
Background: How Turbolinks works
In the Android Turbolinks adapter, the single shared WebView instance is never destroyed. Instead, the WebView is moved between activities. When a new WebView activity is instantiated, we detach the shared WebView from the previous activity and reattach it to the newest foreground activity. This same process happens in reverse when going back/an activity is destroyed – it is removed from its current parent and re-attached to the foreground activity.
In order to achieve moving a shared view around, we leveraged public Android APIs to move the WebView between View hierarchies as well as to switch its context (MutableContextWrapper) to whichever activity was in the foreground.
What changed and why the deprecation?
This system worked well and without issue for 2 years.
But in January 2018 Chromium 64 was released. There was a small but significant change to its accessibility implementation that required that the original Context object be maintained and accessible. But because we were changing the context of the WebView each time a new activity was loaded, any user with accessibility services enabled would potentially run into an unexpected state (the original context could be missing), and therefore crash.
On 2/5/18 we released a patch to work around this issue by catching and swallowing the exception. This is an admittedly leaky patch, but one that slows the bleeding (there is a small memory leak that results for users with accessibility services on, but there’s no way around this for now).
We tried to make our case with the Chromium team that this change was a regression and should be reconsidered. But although MutableContextWrapper is a valid public Android API, the Chromium team consistently reiterated that relying on that wasn’t a good idea and that swapping contexts would always be a risky proposition. In the end, the Chromium team was unwilling to make any changes to their implementation and advised us to change our approach or live with this issue.
Context swapping is a core concept for the Turbolinks Android Adapter, so both Chrome 64 and the Chromium organization’s continued recommendation to not alter the WebView’s context gave us pause. It soon became clear to us that constantly working around context swapping wasn’t going to be viable in the long term, and that we needed to focus our efforts on a far more stable, modern approach to WebView performance and navigation.
We’ve already begun investigating other options and techniques that would give us the performance benefits of Turbolinks but without the risk of context swapping. The intial prototypes are based on Kotlin and Android Jetpack (specifically its Navigation Architecture Components) and it looks promising. Kotlin gives us so many modern language features to work with, while Google’s new opinionated single activity approach bypasses any context swapping issues we ran into previously.
We are very early in the prototype stage, so we still don’t know the exact shape or even a rough timeline of when Turbolinks Android 2.0 might be available, but we plan to have something available in 2019.
Thank you for supporting Turbolinks Android 1.0, and we’re excited to share 2.0 when the time comes.