preface
I highly recommend reading this article on Android componentization best Practices first
This article is a summary of thinking after reading practice, more inclined to practice steps.
Componentized development architecture
Componentized development is basically this architecture, with the key distinction between base and Base_Custom component content.
There are two concepts involved here: modularization and componentization. The two concepts are essentially the same in terms of reducing code coupling. The difference lies in content.
Componentized development steps
Step 1: Create the component
File — >New — >New Moudle — >Phone & Tablet Moudle
After creation, it is a project, similar to app, which will create related resource files by default. “Business Module Preference”
File – > New – > New Moudle – > Android Library
After creation is a moudle “Component preference”
Step 2: Code
In the process of coding, we need to pay attention to the aggregation of resources and code, or follow the principle of doing your own thing and reduce the coupling.
-
resources
-
The image resource Drawable, which needs to be stored in its own directory, like the common return key, is stored in the base component;
-
Color value color, do not share, not much, write in their own component;
-
The dimension DP, which is basically unchanged, can be placed in the base component;
-
The style style, which refers to the Activity theme, can be defined in the base component and inherited in the component, thus ensuring both the overall app style and specialization.
-
In order to ensure sufficient isolation of resources within the component, we can standardize the name, modular name, such external calls, less prone to error.
For example, the login module IC_login_phone login_phone_hint_TEXT…
To be strict, you can configure the named prefix in the build.gradle file so that if you do not code in this format, it will float red. For XML files only, the images need to be properly named themselves.
android { resourcePrefix "login_"// Other configuration... }Copy the code
-
-
code
- Common base classes, utility classes, etc. are placed in the base components
- To prevent external direct references to classes within a component, this can be used when integrating into a project
runtimeOnly
dependencies { ... runtimeOnly project(':moudle_shop')}Copy the code
Step 3: Debug the configuration
After the code is written, it needs to be debugged separately or integrated into the APP, so two modes need to be configured.
- create
gradle.properties
File that defines properties to distinguish between the two modes
/ / such asfalseRepresents integration debugging,trueDebug isSingleRun =false
Copy the code
-
Configure it in the build.gradle file
- Configuring project Types
if(issinglerun.toboolean ()) {// Debug alone should be the project type apply plugin:'com.android.application' } else{// Integrate debugging as library integrated into app plugin:'com.android.library'} android{ ... }...Copy the code
- configuration
applicationId
Android {defaultConfig {// applicationId needs to be configured for separate testsif (isSingleRun.toBoolean()) { applicationId "com.xx.moudle_xx"}}}Copy the code
- configuration
AndroidManifest.xml
Separate tests require a launch page entry, so the manifest file also needs to be configured
android{ sourceSets { main { if(issinglerun.toboolean ()) {// Create a new manifest folder, store the manifest file, set the start page entry manifest.srcfile'src/main/manifest/AndroidManifest.xml' } else { manifest.srcFile 'src/main/AndroidManifest.xml'}}}}Copy the code
- configuration
Applcation
Each component needs to be initialized. Common components (such as network frames and image frames) can be initialized in the base component. How to initialize some of their own modules? Integration tests do not initialize the component’s Application.
Here we can define BaseApp 4 in the base component. The dynamic configuration of the component Application
-
At this point, the debugging configuration is complete. The purpose of the configuration is to facilitate the testing of components when they are independently developed and integrated into the app. Test the configuration by setting the isSingleRun property in the gradle.properties file to true.
Step 4: Debug test
-
Set isSingleRun to true, and you can debug separately, just like the app project.
-
Set isSingleRun to false and integrate into your app to integrate your tests.
Integration testing has a question: How do I jump to an Activity in a component? Need to use Alibaba open source ARouter
It is recommended to read Android componentization Best Practices iv. Interface hopping between components.
ARouter Configuration steps:
Configure build.gradle in the base component
android { defaultConfig { ... javaCompileOptions { annotationProcessorOptions { arguments = [ moduleName : project.getName() ] } } } } dependencies { api 'com. Alibaba: arouter - API: 1.3.1'// Arouter - Compiler's annotation dependency requires that all modules that use arouter add a dependency on annotationProcessor'com. Alibaba: arouter - compiler: 1.1.4' } Copy the code
Component Configuration
android { defaultConfig { ... javaCompileOptions { annotationProcessorOptions { arguments = [ moduleName : project.getName() ] } } } } dependencies { ... annotationProcessor 'com. Alibaba: arouter - compiler: 1.1.4' } Copy the code
Initialize in app main program Application
// This break must be written, otherwise it will not take effect, I thought I did not need to print the log, but it took a long time to find the bugif(buildconfig.debug) {// These two lines must be written before init, otherwise these configurations will not be valid during init arouter.openlog (); // Prints the log arouter.openDebug (); // Enable debug mode (if running in InstantRun mode, debug must be enabled! } ARouter. Init (this);Copy the code
The component in which the Activity is started configures the path, which must start with “/” and have at least two levels
@Route(path = "/test/test") public class TestActivity extends BaseActivity {} Copy the code
The main program starts the Activity in the component
ARouter.getInstance().build("/test/test").navigation(); Copy the code
-
This is the end of individual debugging and simple integration debugging, and the next step is more about integration debugging, how to ensure that components in the case of a high degree of convergence are available to each other.
Data transfer between components
The whole idea is to define interfaces in the underlying components through which data is passed between components, completely decoupled.
Thank you
Best practices for Android componentization