The author | bamboo

Address |

Statement | this is the original bamboo, release has been authorized, without author permission please do not reprint


Gradle plugin is also updated to 3.0.0. At present, all major open source libraries are doing gradle3.0.0 compatibility. I have also upgraded the open source component solution DDComponent. DDComponent is compatible with gradle3.0 and can be used directly. For information on how to migrate to gradle3.0.0, see the official migration guide.

While there were no compatibility issues, there was an unexpected benefit during the upgrade process, which was that gradle3.0.0 has better and better support for code isolation. Why the focus on “code isolation”? You can review the previous two articles on the practice of Android radical componentization and the release of Android Radical Componentization demo. The DDComponent componentization scheme mentioned in these two articles is labeled as “radical”. Although it is a bit of an exaggeration, But mainly to emphasize the difference between DDComponent and previous componentalization solutions is that DDComponent implements absolute isolation between components, completely invisible from each other during code development, a completely decouple idea. To achieve this isolation, I make an artificial distinction between compile and run time, with no dependencies between components at compile time (during development), but surface-add dependencies at package time and run time. See the previous two articles and the Github source code for details.

Gradle does have a similar feature. Apk dependency syntax ensures that dependent libraries are only visible at runtime, but not at compile time. This should have worked for me, but I ran into a pit: in gradle2.+, apK dependencies can only be JARS, not AAR, but the output of our component is aar because it contains various resources! So I finally chose to give up apK syntax.

In the latest Gradle3.0.0, apk has been replaced with runtimeOnly, which does the same thing, but I noticed that runtimeOnly can add AAR dependencies! I’m really excited about this. Isn’t this the feature I’ve been dreaming about? With this sword, the componentized scheme can be made thinner ah. So I experimented on the App and came to the conclusion that runtimeOnly does solve some problems, but it is not enough. I’ll elaborate on code isolation, resource isolation, and debug switching (standalone and integrated), as well as what DDComponent can do.

Code isolation

Before we talk about code isolation, let’s take a quick look at gradle3.0.0 syntax changes for adding dependencies.

First of all, compile has been abandoned, but divided into two parts: implementation and API. The API function is basically the same as that of compile before. Implementation is more advanced in that dependencies added with implementation are not referenced by other components at compile time, but are fully visible at run time. This is also a form of code isolation. So for example,

Implementation lib1 implementation lib1 implementation lib1Copy the code

Before gradle3.0.0, it was completely possible for B to reference classes in lib1, but now B can’t do this at compile time, only at run time. This kind of thinking is similar to the idea that “your subordinates’ subordinates are not your subordinates.” But this isolation does not work between components, and in the example above all classes of A are still fully visible to B, that is, no isolation is done. Implementation is an effective way to reduce compile time. As in the example above, lib1 has changed and now you only need to compile A. Before, B might also use lib1, so you need to compile B and A at the same time. According to official advice, you should use Implementation to add dependencies in most cases.

There are also two changes, the APK syntax will be replaced by runtimeOnly and provided will be replaced by compileOnly. One big change to runtimeOnly is aar support, but compileOnly will still only support JARS!

To summarize, gradle3.0.0 has four syntax features and code isolation:

As you can see from the figure above, runtimeOnly has the best code isolation effect! But can it be used directly? The answer is no.

Resource isolation

In previous articles, code isolation has been emphasized, but another layer of complete isolation between components is resource isolation, otherwise it is easy to create coupling between components. This is mentioned in the “debug alone” section of this article, where each component needs to specify a resourcePrefix, resourcePrefix, to avoid resource name conflicts after integration. In other words, a complete componentization should not only make code unreferable, but also resources unreferable!

But runtimeOnly is still resource isolated. I tested it on the DDComponent open source library. The app references shareComponent components through runtimeOnly, although the shareComponent code is not visible. But resources can still be used directly by the app and run successfully.

At this point, replacing runtimeOnly with runtimeOnly won’t work. To achieve this effect, you still need to add an artificial layer of control, just like DDComponent, so it doesn’t look thinner from a componentization perspective, but fortunately DDComponent is simple. People who have a certain gradle foundation can easily understand it.

Debug switch

In addition to the resource isolation mentioned above that prevents runtimeOnly from being used directly, there is another usage issue that needs to be addressed, which is also provided by the Compbuild plug-in in DDComponent: automatic switching between separate debugging and integrated debugging. In standalone debugging, the component is an Application project whose output is an APK file, while in integration debugging, the dependent component is a Library project whose output is an AAR file. For runtimeOnly, aar and JAR are supported, but APK is not, so if you want to switch between debug alone and debug integration, you need to manually modify the Runalone configuration and modify the build.gradle configuration file. It also needs to be synchronized to take effect, which is quite cumbersome.

In DDComponent, this problem is solved by “intelligently” identifying the component to be debugged, setting the component to be debugged as the Application project and silently changing other components it depends on to the Library project, with immediate effect. It’s completely transparent to developers. Developers can debug any component by clicking on the RUN section of AS. The figure of the RUN functional area of AS is AS follows:


To sum up, we can summarize DDComponent and Gradle3.0.0:

(1) After upgrading to Gradle3.0.0, you can continue to use DDComponent without special compatibility

Gradle3.0.0 provides implementation and runtimeOnly syntaxes, both of which provide some degree of code isolation. We recommend that you use them in the future

(3) Implementation and runtimeOnly still meet the requirement of componentization in resource isolation and debug switch, so we still need to use the full isolation and switch at will provided by DDComponent.

I added the gradle3.0.0 branch to the source code of DDComponent and replaced it with the corresponding syntax. Welcome to continue to support the componentalization solution produced by “Get” APP.

The related

1 Fully componentized Demo for Android is released

2 Android componentization – Best practices for Routing Design