Android 组件化框架 ComponentLight

以下内容针对想要实现工程组件化开发的中小型项目
ComponentLight 是一款 Gradle 插件,无代码侵入,可以理解为组件化辅助工具。

本文将通过以下问题,逐步说明 ComponentLight 的用途和用法。

  1. 为什么要用组件化框架
  2. ComponentLight 能做什么
  3. ComponentLight 怎么用

一、为什么要用组件化框架

为什么要用组件化框架来实现项目组件化,直接利用 module 实现的项目组件化有什么问题吗?

通过创建 module、手动设置依赖的方式可以实现项目组件化,但是效果不好,实际开发中有暗病。

组件化结构的问题

在说问题之前,我们先来看下常见的组件化结构。

架构

项目分析

假如有这么一个项目(如上图),它的 app 模块是程序入口,有阅读(reader)、我的(me)、登录(login)三个业务模块,以及 base-all、base-reader 俩个基础模块。

为了方便说明,我把 app、reader、me、login 等业务(功能)模块称为组件,base-all、base-reader 称为基础库。

上面的项目,组件之间互不依赖,开发时不能直接引用,安全无耦合。同时基础库被组件依赖,组件之间可以依赖基础库做信息传递。

回顾下 Android 组件化。组件化是为了实现业务隔离开发,消除耦合的同时提升开发效率,为此要达到以下效果:

  1. 功能组件化。功能之间独立,开发时不能直接相互引用。这样有利于负责人独立开发自己的组件,至少拉代码时不用担心冲突、删组件时不用担心耦合。
  2. 组件独立化。各组件能作为 app 独立运行,不仅调试起来边界清晰,而且提升了编译速度。即,组件能随时从主项目插拔。

上面的项目中,reader、me、login 相互独立,表现在开发时,不能直接依赖;打包时,由于都被 app 依赖,所以可以全部打包到 apk 里。看似实现了组件化,但是实际操作起来却有很多不方便的地方:

首先,在组件独立化上,每次切换独立运行,要先修改 build.gradle 为 com.android.application、添加 android.sources,然后指定入口 Activity、移除主工程对它的依赖、Rebuild,一大堆操作后才能运行。操作繁琐复杂且耗时,本来组件独立化是为了方便调试、增快编译速度,怎么像是赔了夫人又折兵?

再者,有类似这样的场景:me 组件意为"我的",它展示的是用户的数据,既然涉及用户数据,必然离不开 login 组件。也就是说,me 如果独立运行,需要把 login 打包在内。那怎么做呢?让 me 组件直接依赖 login?此时 me 都可以直接引用 login 的代码,业务功能何来独立?那打包时再手动添加 login 依赖?你确定组件化不是自找麻烦。好,那再创建一个类似 app 的壳模块,让它包含 me 和 login,然后将壳模块独立启动,总可以了吧。确实可以,但是随着项目日益扩大,壳模块也会日渐增多,冗余的壳模块导致整个项目非常乱。

问题总结

分析了这么半天,核心问题就俩个:

  1. 独立运行可行性低,复杂的流程让人望而却步。
  2. 通过壳来实现 "开发时组件无依赖、独立运行时又能把必要的组件打包进去" 的方式很不灵活。

二、ComponentLight 能做什么

既然知道了上述问题,那 ComponentLight 自然就是为解决这俩个问题而生。

首先看下使用了 ComponentLight 后,各组件如何独立运行:

组件独立运行

直接在上栏中切换-运行即可。

然后看下组件 me 如何在不依赖壳模块的情况下,开发时不依赖 login(不可直接引用 login 代码,组件独立)、而在独立运行时自动打包进必要组件 login。只需要在 me 模块的相应配置文件(module-config.properties)里如下声明:

depend_component=login

利用组件化框架可以极大的简化组件化过程中繁琐复杂的流程,最大程度的关注业务开发。

三、ComponentLight 怎么用

1、引入依赖

在项目根 build.gradle 中添加代码

buildscript {
    ...
    dependencies {
        ...
        classpath('com.dixon.plugin:component_light:1.0.0')
    }
}

2、配置模块

2.1、应用插件

找到各个 modulebuild.gradle 文件,移除 apply plugin: 'com.android.application'apply plugin: 'com.android.library',用 apply plugin: 'com.dixon.component' 替代。

apply plugin: 'com.dixon.component'

android {
    compileSdkVersion xx

    defaultConfig {
        minSdkVersion xx
        ...

对于基础库可以不使用 ComponentLight,但推荐使用,以表明基础库在组件化项目中的层级关系。

2.2、声明模块关系

在各个 module 目录下均新建 module-config.properties 文件,用来声明模块关系。

位置如下图:

模块关系位置

该文件的内容如下示例:

module_type=application
depend_component=login,me,reader
depend_base=baseall

下面说明声明的意义和用法。

① module_type

表明当前模块的类型,这个属性最终将结合打包环境决定当前模块是 com.android.application 还是 com.android.library。它的参数如下:

参数 意义
application 表明当前模块是工程主模块。对应到上述项目中就是 app,不需要配置 runalone 即可独立运行,关于 runalone 配置后面会说。
component 表明当前模块是组件。该组件可独立运行,但要配置 runalone。
library 表明当前模块是组件。该组件不可独立运行,不需要配置 runalone。
base 表明当前模块是基础库。该基础库不可独立运行,不需要配置 runalone。

其实 library 和 base 本质上没有区别,但是意义上是有分别的。
library 表示的是业务组件,和 component 同级,不能独立运行可能是因为没有必要。
base 则是基础库。

综上,module_type 决定了当前模块是否可独立运行,和组件间的开发可见性没有关系。

② depend_component

当前组件 独立运行时 需要依赖的其它组件。

depend_component 参数声明了当前模块在业务意义上需要依赖的其它同级组件,并且当前模块独立运行时,这些依赖会被正确打包进 apk。被 depend_component 配置的组件在开发时并不会产生依赖,也就是说,它用于解决传统组件化依赖壳的问题。举几个例子:

模块 me 配置 depend_component=login
则 me 在开发时,无法直接引用 login 的代码。
但 me 在独立运行时,会将 login 正确打包进来,不再需要手动配置或依赖壳。
模块 app 配置 depend_component=me
模块 me 配置 depend_component=login
将 app 作为主工程打包,则 me 跳转 login 会【失败】
depend_component 决定了当前组件依赖的其它组件,如果要从 app 跳转至 login,不管是直接的还是间接的,app 都必须声明需要组件 login。

③ depend_base

表明当前模块依赖的基础库。

depend_base 声明的基础库,会被当前模块在任何时候依赖。也就是说不仅开发时能直接引用,运行时也会一并打包。

不同于 depend_component,假如组件 A 依赖组件 B,组件 B 依赖基础库 b,则 A 组件开发时虽然不能直接引用基础库 b 的代码,但在运行时会将基础库 b 正确打包进来。这是因为基础库 b 是组件 B 运行的基础,理论上是组件 B 的一部分,组件 B 缺少基础库 b 将无法运行,所以即使 A 的 depend_base 没有声明 b,b 也将正常打包进 apk。

上面三个参数分别声明了模块类型、组件关系、基础库关系,理论上就声明完了。

但是要某组件独立运行,除声明 module_type=component 外,还需要在 该组件模块下 配置 runalone

2.3、配置 runalone

module/src/main 下新建 runalone 文件夹,将 AndroidManifest.xml 拷贝一份至 runalone 文件夹下,并指定启动 activity

这里我是这么配置的:

runalone

runalone 中的代码仅会在组件独立运行时用到,不会打包进主工程或其它独立组件中。

关于 runalone,开发者可以按需自行定制,但至少要满足最小独立启动要求:

1.runalone 中有 AndroidManifest.xml;
2.AndroidManifest.xml 配置了 package;
3.AndroidManifest.xml 配置了默认 Activity。

可能会出的问题:
1.AndroidManifest 文件记得检查是否配置了 package。(有的会自带,没有包名怎么启动~)
2.明明配置了启动 Activity,却报 default activity 不存在,重启即可。
3.如果独立运行后,启动闪退,可能是因为你的资源文件找不到。尝试将资源放在 base 模块下。
4.独立运行后,如果新增四大组件,系统会自行声明到 runalone-AndroidManifest.xml 中,记得手动同步至原 AndroidManiest.xml,以保证主工程正确运行。

配置完毕后,Rebuild 即可。

附 runalone 的文件位置:

manifest.srcFile "src/main/runalone/AndroidManifest.xml"
java.srcDir "src/main/runalone/java"
res.srcDir "src/main/runalone/res"
assets.srcDir "src/main/runalone/assets"
jniLibs.srcDir '../app/src/main/jniLibs'

四、尾声

ComponentLight 是组件化的辅助性插件,通过使用它,组件可以随时运行调试,并在摆脱了壳的束缚的同时,保证开发独立性和运行完整性。

bug 和建议可以直接反馈至 github 或文章下边。本人能力有限,错误在所难免,见谅。

Demo Github
插件源码 Github

[TOC]

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,200评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,526评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,321评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,601评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,446评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,345评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,753评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,405评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,712评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,743评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,529评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,369评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,770评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,026评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,301评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,732评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,927评论 2 336