Public number: program ape development center hope to write something that can help you 🤣🤣

Last time, we talked about MVC, MVP and MVVM. In a narrow sense, the architectural concept of Android is right here. No matter how it changes, it is always adding and subtracting some marginal things.

Starting with this article, we intend to explore the idea of mobile architecture in a broad sense; Including now still relatively hot modularization, componentization, plug-in and other architectural ideas. The purpose of this article is to explain the design concept of the current mainstream architecture, so that you can understand the current form of architecture, and what design ideas are used, what design ideas, as a guide…

One, modular, component, plug-in

The above concepts have been mentioned for a long time. Perhaps some of our compatriots are not very clear about these concepts. They generally know what they are, but they do not know what they are in detail. Now let’s parse it out.

Ii. Single project mode

Mobile development was born, we develop mobile projects, I believe most of the use of single-project single-task development mode, without saying a word, directly started to write, is that right?

New Project -> Subcontract -> Write. I believe they have experienced, but also write more cool, why?

This model does not involve messy processing, fast start, fast development, agile enough. So what’s the reason? Mobile Project has just started, and all projects are small. Some additional services have not been tied to the App.

1. Modularization

Android Studio came out with a new concept, Project, Module… Module; The common package, which was then separated AS a package, is now Module in AS.

As you all know, Module contains two formats: Application and Library. In other words, a Module is a small project and a Module in the concept of AS.

So we started designing the common module, the Common_business module, and even the DB module. What are the benefits of modules?

Compared to packages, modules are more flexible, less coupled, and can be plugged in wherever they want. According to different concerns, the shared parts of a project are extracted to form independent modules, which is modularity.

Of course, modularity includes not only common parts, but also business modules.

2. Componentization

Look at the forum at ordinary times, a lot of people are asking: what is the difference between modularization and componentization? What’s the difference? It’s small; But it’s not exactly the same idea. Through the above concept of modularity, should have an understanding of modularity, so what is the difference?

Componentization is an evolution, a variation, based on the idea of modularization. Componentization is the concept of modularization. But what’s at the heart of componentization? Is the transformability of a module’s role. Yes, it’s convertibility.

At the core of componentization is the transformation of roles. When packing, library; In debugging, it’s application.

How do you understand the concept of componentization?

Module has two modes: Application and Library

Library is a reference library, such as common, that you extract. Application is an APK and a complete project.

During debugging, I only care about the module I am in charge of, and I hope that my module is a separate APP, because it is smaller and more specific. Comparatively speaking, modification and debugging will save more time and worry, and compilation will be faster. Imagine when you need to change a piece of code, focusing on yours as well as someone else’s. Or is it more comfortable to compile 10 gigabytes of code for a project or 1 gigabyte of code for a project?

3. Plug-in

Another question: What’s the difference between plugins and componentization?

Plugins are strictly a modular concept. The division of a complete project into different plug-ins by business is an embodiment of divide-and-conquer. Divide the whole into parts and cooperate with each other. Smaller modules are easier to maintain.

Plug-in change is also a kind of embodiment of modularization in principle, and componentization is not a concept. So, what’s the difference?

The unit of componentization is a module. The unit of plug-in is APK (a complete application). Componentization decouples and speeds up compilation, isolating parts that don't need attention. Plug-ins also decouple and speed up compilation, while implementing hot plug, or hot update. The flexibility of componentization is to switch according to the loading time and separate independent business components. For example, the flexibility of the plug-in of wechat moments of friends can be dynamically downloaded and updated when apK is loaded, which is more flexible than componentization. All the componentalization can do is, I already have a friend circle, and I want to debug, maintain, decouple from other people. But it's relevant to the whole project. It can be said that the plug-in circle of friends is an app, AND I need to integrate it into the wechat app. In fact, it can be seen from the name of the framework: group and plug. Group is a system, you divide wechat into circle of friends, chat, address book according to the sense of independent module, but not in the real sense of independent module. Insert is different APK, you put the wechat circle of friends, chat, address book alone to make a completely independent APP, when you need wechat plugged together, it is a large APP. Plug-in loading is dynamic, which is important and a source of flexibility.Copy the code

The above is the analysis of the three ideas, I believe that should be able to understand the specific meaning of different concepts and differences. In “Thoughts and Conclusions on Mobile Architecture”, I pointed out that there are no more than two aspects of architecture: layering and communication. In fact, the broad architecture can also be said to be these two aspects: sub-module (subsystem) partition and communication.

4. Submodule division

In addition to the common part, the division of business modules is particularly important. Compared with architecture in the narrow sense, the division of subsystems in the broad sense tests technical experience and business understanding.

5. Communication mode

Modular communication means, nothing more than mutual introduction; I extracted common, and other modules used the communication mode that would naturally be introduced into the module componentization. It can be divided into many kinds, with implicit and routing as the mainstream. The implicit presence reduces decoupling and flexibility, so routing is the dominant plug-in communication method, and each plug-in is itself a different process. Therefore, the communication mode tends to be interprocess communication with similar Binder mechanisms

So much nonsense, in fact, as a guide to componentization, this is meant to explore the idea of componentization, well, this is only about ideas; In fact, the idea is clear, combined with a certain technical reserve, can be achieved by their own. All right, let’s cut to the chase…


3. Technical preparation for componentization

  • Reflection and apt
  • Gradle with groovy
  • Routing mechanism

The intelligence report

To do a thing, we should first understand what we need to do, then divide the steps, which steps to do, and finally solve each step. That’s a divide-and-conquer way of thinking, and it’s certainly not just an algorithmic way of thinking. Only then can we build information and not be scared into giving up.

The idea of componentization is to switch Module modes. As mentioned above, when packaging, the business Module is Library; When debugging, the business Module becomes the Application.

1. How to switch module modes?

I’m sure you can think of defining a Boolean variable as a switch. Set the module mode according to the switch, as follows

if (isModule) {
    apply plugin: 'com.android.application'
} else {
    apply plugin: 'com.android.library'
}
Copy the code
2. What is the difference between the two modes?
1\. ApplicationId (package configuration) only exists in the Apply Plugin:'com.android.application'mode2Manifest.xml (home page configuration) In integration mode, use manifest.xml configuration under app module; In component mode, the component's own manifest.xml configuration is used3Different components must have their own initialized resources or frameworks, so custom applications are also necessary. However, in integration mode, duplicate applications are createdCopy the code
3. Problems
Fault 1: Unified configuration of multiple service modules
Problem 2: Application distribution
Problem 3: Conflict of resources
Note: Different business modules are not allowed to depend on each other

Solution 1:

Configure different modules (20 service modules) in a unified manner. SO Easy to implement uniform configuration in Java code, but what about in Gradle? That is to define a configuration file to store the items that need to be configured. The following

ext {

    isModule = false // Component switch: true component false integrated

    defaultConfig = [
            minSdkVersion            : 14,
            targetSdkVersion         : 26,
            versionCode              : 1,
            versionName              : "1.0",
            testInstrumentationRunner: "android.support.test.runner.AndroidJUnitRunner"
    ]

    android = [
            compileSdkVersion: 26
    ]

    applicationId = [
            app  : "com.archer.componentsarchitecture",
            card1: "com.archer.card1",
            card2: "com.archer.card2"
    ]

    supportLibrary = "26.1.0"
    appcompatv7a = "com.android.support:appcompat-v7:${supportLibrary}"

    resourcePrefixs =[
            card1: "card1",
            card2: "card2"
    ]

    router = [
            arouter: "Com. Alibaba: arouter - API: 1.2.1.1." ",
            processor: "Com. Alibaba: arouter - compiler: 1.1.2.1"]}Copy the code

Create a config.gradle under Project (what? Can’t create it? Rename & Clear by making a copy of Project build.gradle. Xt is a non-modifiable extension parameter provided by Groovy.

Feel free to define your own configuration, such as code. Here are two concepts:

  1. The placeholder ${supportLibrary} occupies a position and is supplemented with variables in {} for consistent configuration
  2. Android = [compileSdkVersion: 26] This defines a Map to store Key and Value pairs, separated by,. This is groovy. Android is the name of the Map, you can use your own name, but be careful not to conflict with system variables

Above is the unified variable definition, config file config.gradle. The configuration file is defined, so how do you import it?

  1. Build. gradle under [Project] introduces configuration files

    2. References in Module are rootproject.ext. The name you define. However, each time it is tedious to use, it is recommended to define variable implementation, as follows

if (isModule) {
    apply plugin: 'com.android.application'
} else {
    apply plugin: 'com.android.library'
}

def cfg = rootProject.ext.defaultConfig
def drd = rootProject.ext.android
def app = rootProject.ext.applicationId

android {
    compileSdkVersion drd.compileSdkVersion
    defaultConfig {
        if (isModule) {
            applicationId app['card2']
        }
        minSdkVersion cfg.minSdkVersion
        targetSdkVersion cfg.targetSdkVersion
        versionCode cfg.versionCode
        versionName cfg.versionName

        testInstrumentationRunner cfg.testInstrumentationRunner

        resourcePrefix rootProject.ext.resourcePrefixs['card2']

        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [ moduleName : project.getName() ]
            }
        }
    }

Copy the code

Invokes Groovy map the fields in two ways: rootProject. Ext android. The key and rootProject ext android [‘ key ‘]


Solution 2:

Application distribution, wrong practice is different components under the initialization of their own framework, tools, etc. The correct approach is to achieve the initialization of common modules such as network, cache, database and so on in BaseApplication or unified implementation, and to achieve the initialization of their own needs in each Module to avoid repeated initialization and conflict.


Solution 3:

There are two ways to resolve resource conflicts: 1) public resources are recommended to be managed by public modules; 2) module private resources are limited by adding prefixes (only resolve XML conflicts); 3) resources are named cautiously

Resource naming should only be taken care of during development, as the above shared resources and prefixes make it possible to ensure that resources do not clash and are not wasted repeatedly. In case of conflict, leave it to the development specification.


Solution 4:

This is new, that is, said earlier, how to control the application and transformation of the library, all configuration is as follows:

// Free control mode conversion
if (isModule) {
    apply plugin: 'com.android.application'
} else {
    apply plugin: 'com.android.library'
}

Copy the code
// Package name configuration
 defaultConfig {
        if (isModule) {
            applicationId app['card2']}}Copy the code
Manifest.xml application configuration
 sourceSets {
        main {
            if (isModule) {
                // SRC /main create a folder to store manifest.xml and Application in component mode
                manifest.srcFile 'src/main/component/AndroidManifest.xml'
                java.srcDirs = ['src/main/java'.'src/main/component/java']}else {
                // Library mode does not require Application
                manifest.srcFile 'src/main/AndroidManifest.xml'
                java.srcDirs 'src/main/java'}}}Copy the code

Build. Gradle on android in the corresponding Module


This article was originally intended as an idea for the Router principle, but it was intended as a guide from the concept of modularization to the core concept of componentization and preliminary implementation. Because there are a lot of people who may not understand these concepts very well, including me before, such as modularity and componentization.

From the whole point of view, componentization is nothing more than the realization of a transformation and the solution of some problems involved in the transformation process. It’s not that hard, there are some potholes, only to be filled in further as encountered during development.

The core of componentized configuration is the Library and application toggle. The core functionality that is really implemented is the routing implementation part of the communication part. In the next article, how to write the Rooter communication framework by hand.

The last

Because the level is limited, have wrong place unavoidable, rather misdirect others, welcome big guy to point out! Code word is not easy, thank you for your attention! 🙏 If you are studying with me, you can follow my official account — ❤️ Program ape Development Center ❤️. Every week, we will share the technology of Android regularly.