• Android Studio Project Marble: Apply Changes
  • By Jon Tsao
  • Translation from: The Gold Project
  • This article is permalink: github.com/xitu/gold-m…
  • Translator: qiuyuezhong
  • Proofreader: Phxnirvana

Take a closer look at how the Android Studio team built Apply Changes, the successor to Instant Run.

The Android Studio team has a series of in-depth discussionsProject MarbleThis is the first in a series of articles with details and behind the scenes. Released from theAndroid Studio 3.3From the start, Project Marble has focused on ensuring the stability and smoothness of the basic functionality of the IDE. This article was written by Jon Tsao (Product Manager), Esteban de la Canal (Technical Lead), Fabien Sanglard (engineer) and Alan Leung (Engineer) from the Apply Changes team.

One of the main goals of Android Studio is to provide quick code editing and validation tools for your app. When we created Instant Run, we hoped it would significantly speed up your development process, but it doesn’t seem to have done that. As part of Project Marble, we’ve been rethinking Instant Run and have come up with a more practical alternative, Apply Changes. As a new way to speed up the development process, Apply Changes was initially previewed in Canary Channel for Android Studio 3.5. In this post, we want to take a closer look at how it works and our work so far.

Instant Run

With Instant Run, we want to solve two problems: 1) save time in building and deploying applications to devices, and 2) enable applications to deploy changes without losing their running state. To do this in Instant Run, we override your APK at build time to inject hooks for class replacement at Run time. For a more detailed look at the architecture behind Instant Run, see this post on Medium from a few years ago.

This solution generally works well for simple apps, but for more complex apps, it can take longer to build, or cause headaches due to conflicts between the app and the Instant Run build process. As these issues arose, we continued to improve Instant Run in subsequent releases. But we can’t completely solve these problems and make it conform to our expectations.

We took a step back and decided to build a new architecture from scratch, called Apply Changes. Unlike Instant Run, Apply Changes does not change your APK at build time. Instead, we redefine classes at Runtime with the Runtime Instrumentation and newer devices and emulators supported on Android 8.0 (Oreo).

Apply Changes

For devices and VMS running On Android 8.0 or later, Android Studio now has three buttons to control the degree to which applications can be restarted:

  • Run deploys all the changes and restarts the application.

  • Apply Changes attempts to Apply resource and code Changes, and only restarts the Activity, not the application.

  • Apply Code Changes tries to Apply the Code Changes without restarting anything.

Usually only code Changes within the method body are compatible with Apply Changes.

The principle of

Based on our experience and feedback on Instant Run, we adopted a few principles to guide our architectural design and decisions:

  1. Separate build/deploy speed and loss of status. We want to separate the goal of saving build and deployment time from the goal of deploying changes without losing health. Rapid build and deployment should be a goal for all deployment types, whether it’s normal running or debugging, or hot replacement of code. As part of building Apply Changes, we discovered a number of areas that can be optimized for build and deployment speed, and we’ll cover them in more detail in a later article.

  2. Stability is critical. Even if the feature runs 99 out of 100 times at breakneck speed, if your app crashes once because of the feature, and you spend half an hour trying to figure out why, then the other 99 times you get all the revenue is wiped out. Since we adhere to this principle, Apply Changes will not change your APK during build as Instant Run does. As a side effect, in the earlier versions of our stability optimization, Apply Changes were slightly slower than the average speed of Instant Run, but we continue to increase build and deployment speed.

  3. Transparent. The Instant Run button automatically decides whether or not to restart your app or Activity if necessary, and we take this unpredictability and inconsistent behavior into account. We want you to be transparent at all times about what to do with Apply Changes and what happens if your code makes incompatible Changes. So if you detect Changes that are incompatible with Apply Changes, we will now alert you explicitly.

architecture

Let’s take a closer look at how Apply Changes works. After you make Changes to your app, there will be differences between an app that is already installed or running on the current device and an app that Android Studio just compiled. Apply Changes will need to figure out how to Apply those differences. The process can be broken down into two steps: 1) figure out what the difference is, and 2) send the difference to the device and apply it.

To quickly determine the difference, Instead of grabbing the full APK from the device, Apply Changes sends a quick request to the device to pull the corresponding directory and signature of the APK that has already been installed. By comparing these two pieces of information to the new APK, Apply Changes can efficiently find the list of files that have changed since the last deployment, without having to examine everything in the APK. It is important to note that this algorithm does not depend on the build system, as the difference is not compared to the last build, but to the APK installed on the device. Since Apply Changes only operates on differences between APKs, it does not require Gradle plug-in versions to be synchronized with Gradle. This way, Apply Changes can run on all build systems.

After the list of changed files is generated, different actions need to be performed to apply the changes to the running app depending on what has changed, which also determines how far the app needs to restart for the changes to take effect:

Change the resource/asset file. In this case, the application is reinstalled, but only the Activity restarts and the modified resources are retrieved. Only modified resources are sent to the device.

Change the.dex file. Android Runtime for Android 8.0 provides the ability to replace the bytecode of loaded classes, as long as the new bytecode does not change the layout of existing objects in memory. This means that to be compatible with Apply Changes, the changed code has some restrictions: method names, class names, and signatures cannot be changed, nor can their member variables be changed.

But this mechanism doesn’t work at the.dex level, it only works at the class level. Otherwise, if the.dex file contains thousands of classes, it would be inefficient to replace all of them even if only one class changed. For the.dex file, we compare its contents to find the classes that have changed and just replace them. If the replacement is successful (for example, the layout of the class has not changed), the app will be installed in the background to avoid inconsistency between the version of the running app and that of the installed app.

Change the.dex file and the resource file. This case is a combination of the two above. Work with the code first and, if successful, install it with the new resource. In order to load a new resource, the main Activity is restarted. This is an all or nothing operation, and if the code changes don’t apply successfully, nothing will change in the running app.

Change something else. This is a worst-case scenario where files such as Androidmanifest.xml or native.so are changed. In this case, it is impossible to apply the changes without restarting the application. The “Apply Changes” and “Apply Code Changes” operations do not attempt to deploy it; they tell the user that the application needs to be restarted.

For more details on the architecture, listen to the Android Developers Backstage podcastThe latest episode, technical lead Esteban de la Canal discusses Apply Changes in depth.

Compare the.dex file

The previous section explained that Apply Changes requires comparing and identifying which specific classes have been changed (modified/added/deleted) on the device. In order not to add to the overhead of getting a lot of content from the device, it uses D8’s DEX file analysis capabilities in the background to check the contents of every.dex file that Android Studio deploys to the device. Checksums are calculated based on the classes in the.dex file and temporarily stored in a cached database on the host. By comparing the checksum of the newly compiled.dex file with the previous.dex file, Apply Changes can find the changed classes in a very short time.

Delta push

As mentioned above, only the changed files will be sent to the device, which we call “Delta push”. Similar to the DEX file comparison mentioned above, Apply Changes calculates the difference between an installed APK and a recently built APK without needing to get everything from the device. This time, it takes only the Central Directory of the compressed file and conservatively estimates the possible differences between the corresponding APKs. By transferring only what has changed, Android Studio transfers much less data than a full APK upload. In most cases, the total transmitted data is reduced from a few MIBs to a few KiBs.

The following

You can now use Apply Changes in the Canary Release channel in Android Studio 3.5. We welcome to download the latest Android Studio, Apply Changes to your project, and give us early feedback. As a reminder, you can run both the stable version of Android Studio and the Canary Release version. If you have any problems using Apply Changes, please submit a bug with the corresponding idea.log file. We will continue to optimize deployment performance, fix bugs, and listen to your suggestions and feedback.

If you find any errors in the translation or other areas that need improvement, you are welcome to revise and PR the translation in the Gold Translation program, and you can also get corresponding bonus points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.


Diggings translation project is a community for translating quality Internet technical articles from diggings English sharing articles. The content covers the fields of Android, iOS, front end, back end, blockchain, products, design, artificial intelligence and so on. For more high-quality translations, please keep paying attention to The Translation Project, official weibo and zhihu column.