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

简介: 为什么我们要用Gradle管理组件呢?先来看看Android组件化需要实现的目标按照业务逻辑划分模块 项目模块能够单独启动测试 能够根据需求引入或删除某些业务模块 通过不同模块的组合,组成不同的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

引入依赖库
在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"

在项目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
        }
    }

}

 

在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. 功能测试:通常用于测试应用程序端到端的功能,包括从用户的角度与所有外部系统的交互。当我们讨论用户角度时,通常是指用户界面。因为用户界面会随着时间的推移发生变动,维护功能测试代码会变得乏味而耗时。

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

占比如下图所示:

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

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

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

小结

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

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

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

现在加Android高级开发群;701740775,可免费领取一份最新Android高级架构技术体系大
纲和进阶视频资料,以及这些年年积累整理的所有面试资源笔记。欢迎在群里探讨交流移动开发相关的技术跟问题,加群请备注csdn领取xx资料

相关文章
|
18天前
|
存储 Java Android开发
探索安卓应用开发:构建你的第一个"Hello World"应用
【9月更文挑战第24天】在本文中,我们将踏上一段激动人心的旅程,深入安卓应用开发的奥秘。通过一个简单而经典的“Hello World”项目,我们将解锁安卓应用开发的基础概念和步骤。无论你是编程新手还是希望扩展技能的老手,这篇文章都将为你提供一次实操体验。从搭建开发环境到运行你的应用,每一步都清晰易懂,确保你能顺利地迈出安卓开发的第一步。让我们开始吧,探索如何将一行简单的代码转变为一个功能齐全的安卓应用!
|
2月前
|
移动开发 监控 前端开发
构建高效Android应用:从优化布局到提升性能
【7月更文挑战第60天】在移动开发领域,一个流畅且响应迅速的应用程序是用户留存的关键。针对Android平台,开发者面临的挑战包括多样化的设备兼容性和性能优化。本文将深入探讨如何通过改进布局设计、内存管理和多线程处理来构建高效的Android应用。我们将剖析布局优化的细节,并讨论最新的Android性能提升策略,以帮助开发者创建更快速、更流畅的用户体验。
54 10
|
2天前
|
Java Android开发 Windows
玩转安卓之配置gradle-8.2.1
为安卓开发配置Gradle 8.2.1,包括下载和解压Gradle、配置环境变量、修改配置文件以增加国内镜像,以及在Android Studio中配置Gradle和JDK的过程。
11 0
玩转安卓之配置gradle-8.2.1
|
20天前
|
开发工具 Android开发 git
Android实战之组件化中如何进行版本控制和依赖管理
本文介绍了 Git Submodules 的功能及其在组件化开发中的应用。Submodules 允许将一个 Git 仓库作为另一个仓库的子目录,有助于保持模块独立、代码重用和版本控制。虽然存在一些缺点,如增加复杂性和初始化时间,但通过最佳实践可以有效利用其优势。
21 3
|
20天前
|
ARouter 测试技术 API
Android经典面试题之组件化原理、优缺点、实现方法?
本文介绍了组件化在Android开发中的应用,详细阐述了其原理、优缺点及实现方式,包括模块化、接口编程、依赖注入、路由机制等内容,并提供了具体代码示例。
33 2
|
1月前
|
开发框架 Android开发 iOS开发
探索安卓与iOS开发的差异:构建未来应用的指南
在移动应用开发的广阔天地中,安卓与iOS两大平台各占半壁江山。本文将深入浅出地对比这两大操作系统的开发环境、工具和用户体验设计,揭示它们在编程语言、开发工具以及市场定位上的根本差异。我们将从开发者的视角出发,逐步剖析如何根据项目需求和目标受众选择适合的平台,同时探讨跨平台开发框架的利与弊,为那些立志于打造下一个热门应用的开发者提供一份实用的指南。
53 5
|
2月前
|
Android开发
Android Studio: 解决Gradle sync failed 错误
本文介绍了解决Android Studio中出现的Gradle同步失败错误的步骤,包括从`gradle-wrapper.properties`文件中获取Gradle的下载链接,手动下载Gradle压缩包,并替换默认下载路径中的临时文件,然后重新触发Android Studio的"Try Again"来完成同步。
504 0
Android Studio: 解决Gradle sync failed 错误
|
1月前
|
开发工具 Android开发 iOS开发
探索安卓与iOS开发的差异:构建未来应用的关键考量
在数字时代的浪潮中,安卓和iOS这两大操作系统如同双子星座般耀眼夺目,引领着移动应用的潮流。它们各自拥有独特的魅力和深厚的用户基础,为开发者提供了广阔的舞台。然而,正如每枚硬币都有两面,安卓与iOS在开发过程中也展现出了截然不同的特性。本文将深入剖析这两者在开发环境、编程语言、用户体验设计等方面的显著差异,并探讨如何根据目标受众和项目需求做出明智的选择。无论你是初涉移动应用开发的新手,还是寻求拓展技能边界的资深开发者,这篇文章都将为你提供宝贵的见解和实用的建议,帮助你在安卓与iOS的开发之路上更加从容自信地前行。
|
2月前
|
Android开发 iOS开发 C#
Xamarin:用C#打造跨平台移动应用的终极利器——从零开始构建你的第一个iOS与Android通用App,体验前所未有的高效与便捷开发之旅
【8月更文挑战第31天】Xamarin 是一个强大的框架,允许开发者使用单一的 C# 代码库构建高性能的原生移动应用,支持 iOS、Android 和 Windows 平台。作为微软的一部分,Xamarin 充分利用了 .NET 框架的强大功能,提供了丰富的 API 和工具集,简化了跨平台移动应用开发。本文通过一个简单的示例应用介绍了如何使用 Xamarin.Forms 快速创建跨平台应用,包括设置开发环境、定义用户界面和实现按钮点击事件处理逻辑。这个示例展示了 Xamarin.Forms 的基本功能,帮助开发者提高开发效率并实现一致的用户体验。
96 0
|
2月前
|
Android开发 iOS开发 C#
Xamarin.Forms:从零开始的快速入门指南——打造你的首个跨平台移动应用,轻松学会用C#和XAML构建iOS与Android通用界面的每一个步骤
【8月更文挑战第31天】Xamarin.Forms 是一个强大的框架,让开发者通过单一共享代码库构建跨平台移动应用,支持 iOS、Android 和 Windows。使用 C# 和 XAML,它简化了多平台开发流程并保持一致的用户体验。本指南通过创建一个简单的 “HelloXamarin” 应用演示了 Xamarin.Forms 的基本功能和工作原理。
55 0