zoukankan      html  css  js  c++  java
  • Android组件化实践

    1 目的以及组件化与模块化区分

    参考自:分析组件化与模块化之间的区别
    组件化:把重复使用的代码拆分成一个个组件,提供给功能使用
    模块化:按照项目功能需求,将代码拆分成一个个模块。
    区别:组件化是为了重用而拆分模块, 模块化是为了业务分离而拆分模块

    安卓组件化示意图:

    在开发阶段组件1、组件2、组件3都可以单独作为一个应用独立运行,上线时组件1、组件2、组件3 + App壳 + 依赖的其他模块共同构成应用。

    2 组件化具体操作

    demo项目参考地址:

    2.1 统一编译工具版本号以及依赖版本号

    (1) 统一编译工具版本号
    在项目根目录build.gradle中增加编译工具配置

    ...
    ext {
        ...
    
        sdkID = [
                "compileSdkVersion": 30,
                "buildToolsVersion": "30.0.1",
                "minSdkVersion"    : 21,
                "targetSdkVersion" : 30,
        ]
    }
    

    在各模块中引用,如base模块的build.gradle引用(其他模块同理)

    plugins {
        id 'com.android.library'
    }
    
    android {
        compileSdkVersion rootProject.ext.sdkID.compileSdkVersion
        buildToolsVersion rootProject.ext.sdkID.buildToolsVersion
    
        defaultConfig {
            minSdkVersion rootProject.ext.sdkID.minSdkVersion
            targetSdkVersion rootProject.ext.sdkID.targetSdkVersion
            versionCode 1
            versionName "1.0"
        }
        ...
    }
    ...
    

    (2) 统一项目依赖版本号
    同样,在项目根目录build.gradle中增加依赖配置

    ...
    ext {
        ...
        dependenciesID = [
                "appcompat"        : "androidx.appcompat:appcompat:1.2.0",
                "material"         : "com.google.android.material:material:1.2.1",
                "constraintlayout" : "androidx.constraintlayout:constraintlayout:2.0.4",
                "recyclerview"     : "androidx.recyclerview:recyclerview:1.1.0"
        ]
    }
    

    在各模块中引用,如base模块的build.gradle中如下引用:

    ...
    dependencies {
        implementation rootProject.ext.dependenciesID.appcompat
        implementation rootProject.ext.dependenciesID.material
        implementation rootProject.ext.dependenciesID.constraintlayout
    }
    

    2.2 组件化配置

    (1) 在根目录build.gradle中增加变量isRunTotalApp,用于指示各组件是否作为library

    ext {
        ...
        //true 表示各组件共同构成一个应用, false表示各组件可单独成为应用
        isRunTotalApp = false
    }
    

    (2)在App壳中配置对module1的引用

    ...
    dependencies {
        ...
        if (isRunTotalApp) {
            implementation project(":module1")
        }
    }
    ...
    

    (3)在组件module1对应的build.gradle中进行如下配置, 指定应用是否作为library、应用id、应用对应的AndroidManifest.xml文件

    if (isRunTotalApp) {
        //整体作为一个应用时作为library
        apply plugin : "com.android.library"
    } else {
        //单独运行时作为application
        apply plugin : "com.android.application"
    }
    
    android {
        compileSdkVersion rootProject.ext.sdkID.compileSdkVersion
        buildToolsVersion rootProject.ext.sdkID.buildToolsVersion
    
        defaultConfig {
    
            if (!isRunTotalApp) {
                //单独运行时指定应用id
                applicationId "com.example.module1"
            }
    
    
            minSdkVersion rootProject.ext.sdkID.minSdkVersion
            targetSdkVersion rootProject.ext.sdkID.targetSdkVersion
            versionCode 1
            versionName "1.0"
    
        }
    
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            }
        }
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }
    
        sourceSets {
            main {
                if (!isRunTotalApp) {
                    // 单独运行时指定AndroidManifest.xml文件
                    manifest.srcFile 'src/main/test/AndroidManifest.xml'
                } else {
                    // 作为一个组件时指定AndroidManifest.xml文件, 默认AndroidManifest.xml文件
                    manifest.srcFile 'src/main/AndroidManifest.xml'
                }
            }
        }
    }
    ...
    

    单独运行时需要在main/test文件夹下创建AndroidManifest.xml文件,指定组件单独运行时的入口。
    sync项目后即可在运行窗口中看到module1组件,需要时可以将isRunTotalApp设置为true运行整个项目。

    3 组件间跳转: 使用ARouter使用组件间跳转

    再次创建一个组件module2, 和module1配置一样,
    通常而言, 可以通过隐式intent来实现组件间的跳转,还有就是通过路由的方式实现组件间跳转,如使用ARouter框架。
    相关配置参考:ARouter一个组件化工程模板(kotlin,androidX,ARouter)androidX与support-v4包冲突问题

    3.1 ARouter配置

    1、在项目根目录下的build.gradle文件中增加ARouter依赖

    ...
    ext {
    
        arouter_compiler_version = "1.5.1"
        arouter_api_version = "1.5.1"
    
        dependenciesID = [
                ...
                "arouterApi"      : "com.alibaba:arouter-api:${arouter_api_version}",
                "arouterCompiler" : "com.alibaba:arouter-compiler:${arouter_compiler_version}",
                ...
        ]
    
        sdkID = [
                "compileSdkVersion": 30,
                "buildToolsVersion": "30.0.1",
                "minSdkVersion"    : 21,
                "targetSdkVersion" : 30,
        ]
    
        //true 表示各组件共同构成一个应用, false表示各组件可单独成为应用
        isRunTotalApp = true
    }
    

    2、在app壳中配置ARouter的依赖以及需要的AROUTER_MODULE_NAME属性

    apply plugin: 'com.android.application'
    apply plugin: 'kotlin-android-extensions'
    apply plugin: 'kotlin-android'
    apply plugin: 'kotlin-kapt'
    
    android {
        ...
    }
    
    kapt {
        arguments {
            arg("AROUTER_MODULE_NAME", project.getName())
        }
    }
    
    dependencies {
    
        ...
    
        implementation(rootProject.ext.dependenciesID.arouterApi)
        kapt rootProject.ext.dependenciesID.arouterCompiler
    
        ...
    
        if (isRunTotalApp) {
            implementation project(":module1")
            implementation project(":module2")
        }
    
    }
    ...
    

    在module1以及module2的build.gradle文件中同样配置。
    3、在应用的Application中调用ARouter.init方法初始化ARouter。

    package com.example.myapplication
    
    import android.app.Application
    import android.content.Context
    import com.alibaba.android.arouter.launcher.ARouter
    
    class BaseApplication : Application() {
        companion object {
            lateinit var context : Context
        }
    
        override fun onCreate() {
            super.onCreate()
            context = this
            ARouter.init(this)
        }
    }
    

    在需要启动的activity上增加注解,配置路径,用来进行跳转。

    @Route(path = "/module2/MainModule2Activity", group = "module2")
    public class MainModule2Activity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            ...
            String from = getIntent().getStringExtra("from");
            Toast.makeText(this, String.valueOf(from), Toast.LENGTH_SHORT).show();
        }
    }
    

    使用如下代码即可实现跳转,并传递from数据:

    ARouter.getInstance().build("/module2/MainModule2Activity")
                        .withString("from", "" + getClass().getName())
                        .navigation(this);
    

    3.2 ARouter依赖的support包与androidX冲突问题

    在gradle.properties中添加如下属性(参考自ARouter的一个issue以及AndroidX概览):

    android.enableJetifier=true
    

    3.3 demo下载

    链接:https://gitee.com/2820174512/application

  • 相关阅读:
    CF611C New Year and Domino
    CF706C Hard problem (状态机dp)
    CF467C George and Job (dp)
    Vue的响应式系统
    如何更好的使用js?
    关于JS变量和作用域详解
    运算符的应用及流程控制if,switch语句
    js闭包
    js的基础
    js的使用及语法
  • 原文地址:https://www.cnblogs.com/wushengwuxi/p/14105817.html
Copyright © 2011-2022 走看看