通过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资料

相关文章
|
16天前
|
移动开发 Java Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
【4月更文挑战第3天】在移动开发领域,性能优化一直是开发者关注的焦点。随着Kotlin的兴起,其在Android开发中的地位逐渐上升,但关于其与Java在性能方面的对比,尚无明确共识。本文通过深入分析并结合实际测试数据,探讨了Kotlin与Java在Android平台上的性能表现,揭示了在不同场景下两者的差异及其对应用性能的潜在影响,为开发者在选择编程语言时提供参考依据。
|
17天前
|
数据库 Android开发 开发者
构建高效Android应用:Kotlin协程的实践指南
【4月更文挑战第2天】随着移动应用开发的不断进步,开发者们寻求更流畅、高效的用户体验。在Android平台上,Kotlin语言凭借其简洁性和功能性赢得了开发社区的广泛支持。特别是Kotlin协程,作为一种轻量级的并发处理方案,使得异步编程变得更加简单和直观。本文将深入探讨Kotlin协程的核心概念、使用场景以及如何将其应用于Android开发中,以提高应用性能和响应能力。通过实际案例分析,我们将展示协程如何简化复杂任务,优化资源管理,并为最终用户提供更加流畅的体验。
|
20天前
|
缓存 监控 Java
构建高效Android应用:从优化用户体验到提升性能
在竞争激烈的移动应用市场中,为用户提供流畅和高效的体验是至关重要的。本文深入探讨了如何通过多种技术手段来优化Android应用的性能,包括UI响应性、内存管理和多线程处理。同时,我们还将讨论如何利用最新的Android框架和工具来诊断和解决性能瓶颈。通过实例分析和最佳实践,读者将能够理解并实施必要的优化策略,以确保他们的应用在保持响应迅速的同时,还能够有效地利用系统资源。
|
25天前
|
编解码 算法 Java
构建高效的Android应用:内存优化策略详解
随着智能手机在日常生活和工作中的普及,用户对移动应用的性能要求越来越高。特别是对于Android开发者来说,理解并实践内存优化是提升应用程序性能的关键步骤。本文将深入探讨针对Android平台的内存管理机制,并提供一系列实用的内存优化技巧,以帮助开发者减少内存消耗,避免常见的内存泄漏问题,并确保应用的流畅运行。
|
26天前
|
调度 数据库 Android开发
构建高效Android应用:Kotlin协程的实践与优化
在Android开发领域,Kotlin以其简洁的语法和平台友好性成为了开发的首选语言。其中,Kotlin协程作为处理异步任务的强大工具,它通过提供轻量级的线程管理机制,使得开发者能够在不阻塞主线程的情况下执行后台任务,从而提升应用性能和用户体验。本文将深入探讨Kotlin协程的核心概念,并通过实例演示如何在实际的Android应用中有效地使用协程进行网络请求、数据库操作以及UI的流畅更新。同时,我们还将讨论协程的调试技巧和常见问题的解决方法,以帮助开发者避免常见的陷阱,构建更加健壮和高效的Android应用。
35 4
|
18天前
|
Java Android开发 开发者
构建高效Android应用:Kotlin协程的实践与优化
在响应式编程范式日益盛行的今天,Kotlin协程作为一种轻量级的线程管理解决方案,为Android开发带来了性能和效率的双重提升。本文旨在探讨Kotlin协程的核心概念、实践方法及其在Android应用中的优化策略,帮助开发者构建更加流畅和高效的应用程序。通过深入分析协程的原理与应用场景,结合实际案例,本文将指导读者如何优雅地解决异步任务处理,避免阻塞UI线程,从而优化用户体验。
|
23天前
|
Java 编译器 Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
在开发高性能的Android应用时,选择合适的编程语言至关重要。近年来,Kotlin因其简洁性和功能性受到开发者的青睐,但其性能是否与传统的Java相比有所不足?本文通过对比分析Kotlin与Java在Android平台上的运行效率,揭示二者在编译速度、运行时性能及资源消耗方面的具体差异,并探讨在实际项目中如何做出最佳选择。
17 4
|
1天前
|
缓存 移动开发 Android开发
构建高效Android应用:从优化用户体验到提升性能表现
【4月更文挑战第18天】 在移动开发的世界中,打造一个既快速又流畅的Android应用并非易事。本文深入探讨了如何通过一系列创新的技术策略来提升应用性能和用户体验。我们将从用户界面(UI)设计的简约性原则出发,探索响应式布局和Material Design的实践,再深入剖析后台任务处理、内存管理和电池寿命优化的技巧。此外,文中还将讨论最新的Android Jetpack组件如何帮助开发者更高效地构建高质量的应用。此内容不仅适合经验丰富的开发者深化理解,也适合初学者构建起对Android高效开发的基础认识。
2 0
|
1天前
|
移动开发 Android开发 开发者
构建高效Android应用:采用Kotlin进行内存优化的策略
【4月更文挑战第18天】 在移动开发领域,性能优化一直是开发者关注的焦点。特别是对于Android应用而言,由于设备和版本的多样性,确保应用流畅运行且占用资源少是一大挑战。本文将探讨使用Kotlin语言开发Android应用时,如何通过内存优化来提升应用性能。我们将从减少不必要的对象创建、合理使用数据结构、避免内存泄漏等方面入手,提供实用的代码示例和最佳实践,帮助开发者构建更加高效的Android应用。
5 0
|
3天前
|
缓存 移动开发 Java
构建高效的Android应用:内存优化策略
【4月更文挑战第16天】 在移动开发领域,尤其是针对资源有限的Android设备,内存优化是提升应用性能和用户体验的关键因素。本文将深入探讨Android应用的内存管理机制,分析常见的内存泄漏问题,并提出一系列实用的内存优化技巧。通过这些策略的实施,开发者可以显著减少应用的内存占用,避免不必要的后台服务,以及提高垃圾回收效率,从而延长设备的电池寿命并确保应用的流畅运行。