架构:Android 组件化开发

2,033 阅读4分钟

前言

强烈推荐先阅读这篇文章 Android 组件化最佳实践

本文是阅读实践后的思考总结,更倾向实践步骤。

组件化开发架构

组件化开发大体就是这样的架构,最关键的是basebase_custom 组件内容的区别化。

这里涉及两个概念 模块化 和 组件化,这两个本质上是一样的,都是为了降低代码耦合性,区别就在于内容,组件化都是单一功能的集合,模块化就是独立业务线的集合,其实我们都可以称之为组件化。

组件化开发步骤

第一步:创建组件

File——>New——>New Moudle——>Phone & Tablet Moudle

创建后是一个工程,类似app,会默认创建好相关资源文件。「业务模块首选」

File——>New——>New Moudle——>Android Library

创建后是一个moudle「组件首选」

第二步:编码

编码过程中需要注意的就是 资源和代码的聚合,还是遵循 自己的事情自己做 的原则,降低耦合性。

  • 资源

    • 图片资源 drawable,需要用到的放在自己目录下,类似共用的返回键这种,放在基础组件中;

    • 颜色值 color,不要共用,没多少,写在自己组件中;

    • 尺寸 dp,这个基本没啥变化,可以放到基础组件中;

    • 样式 style,涉及到Activity主题的,这个可以在基础组件中定义,组件中继承,这样既保证了整个app风格,也可以特殊化。

    • 为了保证 组件内资源 的 充分隔离,我们可以 规范命名,以模块化命名,这样的外部调用时,不容易出错。

      例如 登录模块 ic_login_phone login_phone_hint_text ...

      严格一点,可以在 build.gradle 文件中配置 命名前缀,这样编码时 不按照这种格式,就会飘红。只针对xml文件,图片还需自己规范命名。

      android {
          resourcePrefix "login_"
          // 其他配置 ...
      }
      
  • 代码

    • 共用的基类,工具类等放在基础组件中
    • 为了防止外部直接引用 组件内的类,可以在集成到工程中时 采用runtimeOnly
    dependencies {
        ...
        runtimeOnly project(':moudle_shop')
    }
    

第三步:调试配置

代码写好后,需要 单独调试 或 集成到app中调试,那就需要配置两种模式。

  • 创建 gradle.properties 文件,定义属性用来区分两种模式
//例如 false表示集成调试,true表示单独调试
isSingleRun = false
  • build.gradle 文件中配置

    • 配置工程类型
    if (isSingleRun.toBoolean()) {
        //单独调试 应该是工程类型
        apply plugin: 'com.android.application'
    } else {
        //集成调试 则作为library集成到app中
        apply plugin: 'com.android.library'
    }
    android{
      ...  
    }
    ...
    
    
    • 配置 applicationId
    android{
        defaultConfig {
            //单独测试 需要配置applicationId
            if (isSingleRun.toBoolean()) {
                applicationId "com.xx.moudle_xx"
            }
        }
    }
    
    • 配置 AndroidManifest.xml

    单独测试是需要一个启动页入口的,所以清单文件也需要配置

    android{
          sourceSets {
            main {
                if (isSingleRun.toBoolean()) {
                    //单独测试 新建一个文件夹manifest,存放清单文件,设置启动页入口
                    manifest.srcFile 'src/main/manifest/AndroidManifest.xml'
                } else {
                    manifest.srcFile 'src/main/AndroidManifest.xml'
                }
            }
        }
    }
    
    • 配置 Applcation

    每个组件,都会有需要初始化的东西,共用的(比如:网络框架,图片框架)可以在基础组件中初始化,那么一些自己模块需要初始化的东西,该怎么做?因为集成测试不会初始化 组件的Application

    这里我们可以在基础组件中定义 BaseApp 4. 组件 Application 的动态配置

  • 至此,调试配置完成,配置的目的就是为了方便 组件 独立开发时测试 以及 集成到app时测试。将 gradle.properties 文件中的 isSingleRun 属性设置为true,测试一下配置是否成功。

第四步:调试测试

  • isSingleRun设置为true ,就可以 单独调试 了,像 app 工程那样。

  • isSingleRun设置为false ,然后集成到app中就可以 集成测试 了。

    集成测试这里有个问题,如何跳转到组件中的 Activity呢?需要用到 Alibaba 开源的 ARouter

    推荐阅读 Android 组件化最佳实践 中的 四、组件间界面跳转

    ARouter配置步骤:

    base组件中配置build.gradle

    android {
        defaultConfig {
            ...
            javaCompileOptions {
                annotationProcessorOptions {
                    arguments = [ moduleName : project.getName() ]
                }
            }
        }
    }
    
    dependencies {
        api 'com.alibaba:arouter-api:1.3.1'
        // arouter-compiler 的注解依赖需要所有使用 ARouter 的 module 都添加依赖
        annotationProcessor 'com.alibaba:arouter-compiler:1.1.4'
    }
    

    组件中配置

    android {
        defaultConfig {
            ...
            javaCompileOptions {
                annotationProcessorOptions {
                    arguments = [ moduleName : project.getName() ]
                }
            }
        }
    }
    
    dependencies {
        ...
        annotationProcessor 'com.alibaba:arouter-compiler:1.1.4'
    }
    

    在app主程序 Application中初始化

    //这断必须写,否则不生效,本以为我不需要打印日志,没写这段,结果花费好长时间找bug
     if (BuildConfig.DEBUG) {        // 这两行必须写在init之前,否则这些配置在init过程中将无效
            ARouter.openLog();     // 打印日志
            ARouter.openDebug();   // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
    }
    ARouter.init(this);
    

    组件中被启动Activity 配置 path,path 必须是 ”/“ 开头,最少两级

    @Route(path = "/test/test")
    public class TestActivity extends BaseActivity {}
    

    主程序启动 组件中 Activity

    ARouter.getInstance().build("/test/test").navigation();
    
  • 至此,单独调试 和 简单的集成调试 完结,接下来更多的就是 集成调试情况下,如何保证组件在高度聚合的情况下互通有无。

组件间数据传递

整体思路就是在基础组件中定义接口,组件间通过接口传递数据,完全解耦。

感谢

Android 组件化最佳实践