通过Gradle自动实现Android组件化板块构建

作者 : 开心源码 本文共6078个字,预计阅读时间需要16分钟 发布时间: 2022-05-12 共149人阅读

image

原文博客地址:Tangpj

不论全世界所有人怎样说,我都认为自己的感受才是正确的。无论别人怎样看,我绝不打乱自己的节奏。喜欢的事自然可以坚持,不喜欢的怎样也长久不了。
—— 村上春树

背景

随着App的不断迭代,业务会变得越来越复杂,业务板块会越来越多,且每个板块的代码也会变得越来越多。为了应对这一场景,我们需要把不同的业务板块划分成一个个组件,在修改业务代码的时候只要要在对应板块修改即可以了。通过高内聚,低耦合的业务板块来保证工程的健壮性和稳固性。现在问题来了,当组件的数量变得越来多的时候,我们如何管理业务组件呢?

原创公告: 该文章为原创文章,未经博主同意严禁转载。

为什么我们要使用Gradle管理组件呢?

先来看看Android组件化需要实现的目标。(什么是组件化构建?)

  1. 按照业务逻辑划分板块
  2. 项目板块能够单独启动测试
  3. 能够根据需求引入或者删除某些业务板块
  4. 通过不同板块的组合,组成不同的App

对于第一点:需要根据技术架构和业务架构来划分板块,这里需要根据实际情况来考虑。我们需要优化的是第二、三、四点。

对于第二点:Android是通过应使用com.android.application或者com.android.library来决定该板块是以App模式还是以Library模式构建。App模式和Library模式的最大区别就是,App能够启动,而Library不可以。所以假如我们的板块能独立启动的话,我们需要每次手动去改动板块的build.gradle文件。好一点的做法定义一个布尔值来判断能否处于debug模式,但是这里有个问题是,不是每个板块都能独立启动的。所以无论采使用何种方案,都需要我们手动管理。

对于第三点:当我们开发好业务板块后,可能我们需要频繁的新添加或者删除某些业务板块。假如是这样的话,我们也是需要频繁手动修改App的build.gradle。

对于第四点:有时候,我们可能会在不同的App中引使用相同的组件(例如:滴滴的普通版和企业版,普通版包含企业版的功能),这个时候,我们也不希望要频繁手动管理组件依赖,特别是在组件还可以独立运行的时候。

所以,在我们实践组件化的时候,最大的问题就是,我们需要频繁的手动build.gradle文件来管理组件应使用的插件和App的依赖。

用Gradle来管理组件

先安利下笔者写的Gradle插件:Calces。假如觉得这个插件有使用的话,可以star下,假如你有更好的想法的话,可以向我提交pull request。

废话少说,一下是通过Calces快速实现Android组件化构建的流程。

Demo地址:SimpleCalces

项目结构:

simple_calces_dir

  1. 引入依赖库
    在Gradle 2.1及更高版本的插件构建脚本代码:
    在项目的build.gradle中

    buildscript {    ...}plugins {  id "calces.modules" version "1.0.11"}

在较旧版本的Gradle中或者需要动态配置的情况下的插件构建脚本代码:

   buildscript {     repositories {       maven {         url "https://plugins.gradle.org/m2/"       }     }     dependencies {       classpath "gradle.plugin.com.tangpj.tools:calces:1.0.11"     }   }   apply plugin: "calces.appConfig"
  1. 在项目build.gradle配置AppConfig

    appConfig {    debugEnable false    apps {        app{            modules ':library1', ':library2'        }    }    modules{        library1{            mainActivity ".Library1Activity"            applicationId "com.tangpj.library1"            isRunAlone true        }        library2{            mainActivity ".Library2Activity"            applicationId "com.tangpj.library2"            isRunAlone true        }    }}
  1. 在modules(子板块)引入板块自动化构建插件 (注意:不需要手动配置com.android.library或者com.android.application)

    apply plugin: 'calces.modules'

这样我们就完成了组件化的构建了,是的,我们不再需要再手动管理单个组件了与App的构建了,通过Calces,我们能实现快速的组件化构建与多App同时构建。

那么问题来了,我们如何实现组件间的通信呢?在简单的项目中,推荐该Demo一样,通过用Android隐式Intent来实现组件间通信。在中大型项目中,笔者推荐用阿里的路由处理方案:ARouter。具体用方法参考官方文档即可以了,用方法十分简单。

注意:在用隐式Intent实现组件件通信的时候需要注意找不到相应组件异常:java.lang.IllegalStateException: Could not execute method of the activity。导致这个异常的起因是找不到目标组件导致的,所以在实际开发的时候,需要捕获这一异常,并且根据项目实际情况来进行实际的解决。用ARouter框架则能通过设置降级策略来实现异常解决(查看ARouter文档理解更多)。

假如只是实现项目的简单组件化,那么看到这里即可以了,假如希望实现更加灵活的组件化架构的读者可以继续看下去,下面笔者将全面分析组件化的优势与笔者总结的组件化构建思想。

组件化构建简述

组件化构建与其说是一种技术,不如说是一种思想。组件化构建是通过对项目重新划分成一个个高内聚、低耦合的板块来处理项目过于臃肿,代码过于复杂的一种架构思想。

我们通过对Google官方的架构演示Demo todo-mvp进行拆分来对Android组件化进行深入的分析。

Demo地址:TodoCalces

todo系列app是Google android-architecture项目中为了演示Android架构的最佳实现而编写的一系列演示Demo。todo app的特点是,它足够简单,代码量少,易于了解。但是又不会过于简单,由于它是一个包含完成功能的App。它实现了任务列表、任务介绍、新建任务、编辑任务、统计任务的功能。

todo-mvp实现的功能:

  • 任务列表
  • 任务介绍
  • 新添加/编辑任务
  • 统计任务

我们将以todo-mvp的功能来划分为4个业务板块,将底层划分为2个板块,分别是superLib(提供mvp架构支持与其它的少量支持库功能)与dataLib(数据支持板块,Room提供底层数据库支持功能)。对于大型项目还可以加入resLib支持板块,使用来存放公共图片资源、字符穿资源、样式等。

架构划分图如下:

Todo Calces Architecture

从架构图可以看出,所有的业务组件都依赖底层库,而APP又依赖于业务组件,APP组件在这里是作为一个独立组件存在的。在一般的组件化实践中,都不包含APP这个组件的,APP组件的存在是有其意义的。

首先,我们的组件化除了实现组件的独立管理和动态配置APP所依赖的组件外,还有一个十分重要的目的就是,通过组合不同的组件,打包多个不同的APP。例如,QQ有分普通版和轻聊版,轻聊版是功能简化版的QQ。假如我们用组件化来管理工程的话,我们只要要把不需要的板块移除掉即可以了。而APP组件在这里的作使用是充任一个包装盒,把需要的组件包装进来。并且我们可以通过控制包装盒的样式来配置不同的APP风格。在这里我们可以通过Application中的Style来实现。

这里我们还是以todo-mvp为例,例如我们需要实现一个不包含统计功能的todo APP,按照我们的原理,我们只要要去掉statistics的依赖即可以了。

架构划分图如下:

Todo No Statistic Architectur

假如nostatsitcs需要不同的配色的方案的话,只要要在AndroidManifest的application标签中配置对应的theme即可以了。

用Calces实现todo-mvp的组件化

通过上面的分析,我们来试下对todo-mvp项目按照业务功能来划分组件。我们先来看看划分后的目录:

todo_calces_dir

好了,我们已经对todo-mvp项目进行初步的划分了。根据上面分析的理论得知,我们的业务板块是可以单独运行的,并且我们能够快速构建一个不包含statistics板块的APP。

我们只要要用Calces就能快速实现我们需要的功能。

按照Calces的教程,我们得知,实现Calces只要要三个步骤:

  1. 引入依赖库
  2. 在项目的build.gradle中配置AppConfig
  3. 在业务板块中引入板块自动化构c持续

第一点和第三点在其它所有项目中的配置都是一样的,在这里不作论述,下面我们看看对于TodoCalces项目,我们要如何配置AppConfig 。

appConfig {    debugEnable false    apps {        app {            mainActivity "com.tangpj.tasks.TasksActivity"            modules ':modules:addtask',                    ':modules:taskdetail',                    ':modules:tasks',                    ':modules:statistics'        }        app2 {            name 'nostatistic'            applicationId 'com.tangpj.nostatistic'            modules ':modules:addtask',                    ':modules:taskdetail',                    ':modules:tasks'        }    }    modules {        addtask {            name ":modules:addtask"            applicationId "com.tangpj.addtask"            mainActivity ".AddEditTaskActivity"            isRunAlone false        }        taskdetail {            name ":modules:taskdetail"            applicationId "com.tangpj.taskdetail"            mainActivity ".TaskDetailActivity"            isRunAlone true        }        task {            name ":modules:tasks"            applicationId "com.tangpj.tasks"            mainActivity ".TasksActivity"            isRunAlone true        }        statistics {            name ":modules:statistics"            applicationId "com.tangpj.statistics"            mainActivity ".StatisticsActivity"            isRunAlone true        }    }}

根据AppConfig可以得出,我们分别配置了2个APP,分别是app1和app2。并且app2中是没有依赖statistics的。现在我们两个APP运行的比照图。

app1(带statistics板块):

todo_calces

app2(不带statistics板块):

nostatistic

从运行图可以看出,app1和app2的配色方案是不一样的,并且app2中不带statistics板块,通过对项目实行正当的划分和引入Calces就能够快速实现组件化构建了。

结论:通过Calces能轻松实现业务组件的管理,多APP的快速构建。当我们的业务组件只有4个的时候,可能无法表现Calces的优势,但是假如我们的业务组件有40个的时候,Calces给我们带来的优势就非常显著了。我们可以通过灵活依赖不同的组件,实现快速构建多个APP的目的。就像Calces的详情图案一样,把组件当成积木来用。

如何测试

Android自动化测试开展来说是一个非常大并且不算简单的工程,在这里笔者不打算开展来说。只是简单的详情组件化构建如何让我们更方便地去测试。

并不是所有的自动化测试都一样,它们通常在用范围、实现难度和执行时间上存在不同。我们一般把自动化测试划分为三种分别是:

  1. 单元测试:目的是测试代码的最小单元。在基于Java的项目中,这个单元是一个方法。单元测试容易编写,快速执行,并在开发过程中针对代码的正确性提供宝贵的反馈。
  2. 集成测试:使用来测试一个完成的组件或者子系统,确保多个类之间的交互能否按预期运行。集成测试需要比单元测试需要更长的执行时间,而且更加难以维护,失败的起因难以诊断。
  3. 功能测试:通常使用于测试应使用程序端到端的功能,包括从使用户的角度与所有外部系统的交互。当我们探讨使用户角度时,通常是指使用户界面。由于使用户界面会随着时间的推移发生变动,维护功能测试代码会变得乏味而耗时。

为了优化投资回报率,代码库应该包含大量的单元测试、一些集成测试以及更少的功能测试。

占比方下图所示:

[图片上传失败…(image-f27759-1532391342632)]

从上文知道,在我们的组件化分的时候,会划分一个基础依赖库(superLib)。基础依赖库为我们的项目提供了基本的支持,并且该库在项目中是比较稳固、并且不包含业务逻辑的,所以在基础依赖库中,我们应该大量应使用单元测试。而集成测试则适使用于我们的数据依赖库(dataLib)中,我们可以通过集成测试来验证产品代码与数据板块的交互。而我们的业务板块中包含了大量的业务逻辑,这部分是经常变动的部分,我们可以为我们的业务板块编写少量UI自动化测试代码,但是由于业务(界面)经常变动的起因,所以这部分测试代码是难以维护,并且复使用性十分低的。。

最后,我们得出的结论是:应该把主要精力放在单元测试上,所以假如当你的精力不足以编写所有测试代码的时候,你应该把主要的精力放在单元测试上,而不是放在收益最小的功能测试上。

关于自动化测试,笔者给的建议就到这里了,假如需要深入了解测试的话,可以自行查找资料,或者者关注笔者的博客。后续的博客中,有可能会写关于自动化测试相关的知识。

小结

通过Calces插件,我们在实现Android组件化时只要要关注如何正当划分组件的架构与如何实现组件间的通信即可以了。对于Android组件化来说,最主要问题有两个:

  1. 大型项目如何正当划分组件板块
  2. 当项目的组件数量非常多的时候如何管理

第二个问题,可以通过Calces快速处理,至于第一个问题,笔者给出的指导就是,业务板块在正当的情况下要尽可能的小,由于越小的板块,越容易达到高内聚低耦合的目的。读者不需要担心项目板块划分得过于细不便于管理的问题,由于Calces能够轻松帮你管理好各个板块。

历史精选

Android开发利器之Data Binding Compiler V2 —— 搭建Android MVVM完全体的基础

关于我

假如这片文章对你有所启发的话,可以关注下笔者的公众号或者GitHub。

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 通过Gradle自动实现Android组件化板块构建

发表回复