Difference between componentization and modularization

  • Componentization focuses mainly on the business logic layer, mainly for the separation of business logic, business logic only
  • The focus of modularity is on the reuse of functionality, which breaks down plugins one by one, for the entire project

The difference between componentization and plug-in

  • Componentization No matter how many modules we break up our business into, we end up generating an APK when we package and go live
  • The plug-in is also divided into many plug-in modules, but after the final package, many APKs become. Finally, we upload it to our server. When users use it, they only need to download the apK response, and then use the dynamic loading technology to load the corresponding activities inside

Advantages of componentized development

  • Instead of running the entire project, we run a single component each time
  • If we want to use a module in a new project, it is easy because each module is a separate Application
  • Because an Application cannot depend on another Application
  • We don’t need decoupling, resources, and so on
  • Componentized development is the cornerstone of large team development

Business logic layer

Public layer

System layer

Componentized development to encounter problems

From the componentized actual combat to solve the problem

  • Create a componentized project
  • Create two Application components and change the name of the MainActivity class to prevent resource naming conflicts

  • We added so many modules, so each module has build.gradle in it. Suppose we need to upgrade the version of the dependent components in a module later, do we need to change the version number in each module? This is definitely not going to work, so we need to create a file that manages our version numbers uniformly and uses the same version control tool for each module
  • There are three ways to do this
  • The first way is to define gradle.properties directly
  • The second way: define it in our entire project build
  • The third way is to create a Gradle file to hold these parameters
  • We take the third approach

  • The file has been created, but our project is not aware of it. How can we make it available to the entire project?
  • Declare it in your project’s build.gradle

  • This declaration tells the project to load our config when our application loads
  • Then we can use our config file under the main App and sub-Module

  • After the change, Sync now can be done, there is no error is successful
  • A new problem arises, we usually change the SDK version number, we below the various dependency library version also need to correspond to it, how to do?
  • Of course, we can solve the problem by defining an array in the same way

  • In the same way, introduce the dependencies of the individual components

  • Gradle files are written in curly brackets. Some of them are equal signs, some of them are colons, and just to explain, we’re going to use curly braces for data sets, and then equal signs for objects, and colons for properties
  • At this point, we will unify the version numbers of various dependent libraries
  • Next question

How do components switch back and forth between Application and various Modules?

  • It’s just a matter of changing the way our components are packaged

  • Change the name of Application here to Library
  • But if we had to manually modify it every time, it would be more troublesome
  • We can add a switch

  • Then configure the switch in the Module
if (rootProject.ext.android.is_application) {
    apply plugin: 'com.android.application'
} else {
    apply plugin: 'com.android.library'
}

apply plugin: 'kotlin-android'
Copy the code
  • At this point, we set the switch to false and see that the components are Library

Androidmanifest.xml file differentiation

  • Since the Application and library androidmanifest.xml files are different, we need to distinguish them
  • Add a manifest folder to the module and copy a copy of the manifest file
  • The manifest file of the library does not require an intent, so we need to remove the intent and some of the code in the Application
<? The XML version = "1.0" encoding = "utf-8"? > <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.login"> <application> <activity android:name=".LoginActivity"> </activity> </application> </manifest>Copy the code
  • After modifying the manifest for each Module, we need to set the manifest file dynamically based on the is_applitaion property
  • Add such code under each module module
sourceSets{ main{ if (rootProject.ext.android.is_application) { manifest.srcFile 'src/main/AndroidManifest.xml' } else {  manifest.srcFile 'src/main/manifest/AndroidManifest.xml' } } }Copy the code

Library modules cannot have applicationIDS

  • What is the cause of this exception?

ApplicationId is set in defaultConfig, but not in library

  • How do I solve this exception?
  • We just add a judgment when setting the applicationId

  • As can be

With modules set up, we’ll eventually have to let our main App rely on our Module when we need to publish

  • As shown in the figure above, we have our App rely on the following two modules

After dependency, we have already published, but now we need to change our module to Application?

  • We change it to true and see that an exception is thrown
  • The exception means that our App module cannot depend on our login module and member module, because they are application, and application cannot depend on application module
  • Then we need to modify the submodule to library, we only rely on those two modules, otherwise we do not rely on them
  • Modify build.gradle under app
dependencies { implementation rootProject.ext.dependencies.publicImplementation if (! rootProject.ext.android.is_application) { implementation project(path: ':login') implementation project(path: ': member')} testImplementation junit: junit: 4. + 'androidTestImplementation' androidx. Test. Ext: junit: 1.1.2 ' AndroidTestImplementation 'androidx. Test. Espresso: espresso - core: 3.3.0'}Copy the code

So those are the basic questions, and there are some more

For example, in a project we need to know whether the current project is Application or Library

  • This is where we need to create the base library
  • Why do you need a base library? Because we need these things for every module

  • Now that the base library is created, how do we write it so that every Module depends on it?
  • Build. Gradle > build. Gradle > build. Gradle > build. Gradle > build

  • That way, we can make only one change in the future
  • Next we need to deal with parameter passing, we need to pass the IS_Application parameter to each module’s buildConfig file
  • We need to add the following code to the build.config file in our BASIC module. Note that this property should be added in all environments
buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            buildConfigField 'boolean', 'is_application', rootProject.ext.android.is_application.toString()
        }
        advanced {
            buildConfigField 'boolean', 'is_application', rootProject.ext.android.is_application.toString()
        }
        debug {
            buildConfigField 'boolean', 'is_application', rootProject.ext.android.is_application.toString()
        }
    }
Copy the code
  • And then let’s Make the project
  • Look in basic’s buildConfig file and find that the properties have been added

  • Now we can use it under the BASIC module
  • Note here that we need to declare a static variable of IS_Application under Application in the Basic module
  • So that each of our modules can use this property
  • The following
package com.example.basic

import android.app.Application

/** * 
 * author: Jafar * date : 2020/11/11 * desc : * 

*/
class BaseApplication : Application() {

companion object {
const val is_application = BuildConfig.is_application
}

override fun onCreate(a) {
super.onCreate()
}
}
Copy the code

  • Of course, not all of our modules can use Application, so our baseActivity is undoubtedly the most appropriate
package com.example.arouterproject

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

/**
 * <pre>
 *     author: Jafar
 *     date  : 2020/11/11
 *     desc  :
 * </pre>
 */
class BaseActivity : AppCompatActivity() {

    companion object {
        const val is_application = BuildConfig.is_application
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }
}
Copy the code
  • We sometimes need to load some classes in the module when compiling, but not when packaging, how to set?

  • As shown above, we simply create a folder, copy the Java classes into it, and add this line of code to sourceSets
  • This line of code declares that my directory is a Java folder
  • The nice thing about this is, when we’re developing, we’re compiling with Application, we’re compiling with temporary code, but what? We don’t need it when we pack it, which means we don’t need it when it becomes library. Reduced random compilation
  • By doing so, we prevent the bugs we get from constantly switching
  • Solve the problem of waste of resources
  • That’s it. Let’s just take care of the details

How do I jump between modules? Handwritten routing can!