Android模块化实践,GitHub标星8k

本文介绍了Android应用的模块化实践,包括APP壳工程、业务层、公共组件层和基础业务层的详细设计。重点讨论了在模式切换、AndroidManifest合并、build.gradle定义等问题上遇到的挑战和解决方案,旨在提升开发效率和代码维护性。
摘要由CSDN通过智能技术生成

从结构上来看,APP被划分成5层,每层的功能具体如下:

APP壳工程

这是一个空的项目,其中只包含了一个Application的子类和一个IntentService的子类,主要用来对APP中使用的各种组件进行初始化,IntentService的作用是为了提高APP冷启动的速度,将各种组件的初始化放在后台线程异步执行,这里需要注意的是,对于在Applicaiton或SplashActivity中就会使用的组件,最好直接在Application中进行初始化,否则会抛出未初始化的异常。

业务层

这里的业务层被划分为Main模块和其他模块(至于划分几个模块,根据自己APP的业务,选择合适的粒度进行划分即可)。这里的Main模块主要包括:新用户引导页,启动页,主页。具体业务方面的页面,都放在具体的业务模块中。

公共组件层

公共组件层主要包括APP中使用的第三方组件,这些组件基本都是现在AP
P的通用功能,为上层的业务层提供支持。至于模块划分,虽然这些都是单独的组件,但是每个做为一个Module未免有些繁琐了,所以还是推荐放在一个Module中。在选择第三方的库时,需要做一定的调研,尽量选择大公司,使用用户多的SDK,同时在使用时最好封装一下,这样后面更换时也方便。

基础业务层

基础业务层主要用来统一APP的代码结构,UI风格等,主要包含以下三个方面:

Android组件的二次封装

主要是对Activity/Fragment的封装,提供了不需网络请求的BaseActivity/BaseFragment和需要网络请求的BaseProgressActivity/BaseProgressFragment, 为页面的代码提供统一的结构,页面的样式提供统一的风格。

业务通用UI

主要包含各种样式的Dialog, 自定义View等,根据APP的设计风格提供统一的样式;

图片操作库

图片操作库ImageSet是对图片组件库(包括Fresco, Glide, Universer ImageLoader)的封装,同时提供了调用系统相机/相册选择&裁剪照片,类似微信选择图片的组件,图片上传,图片压缩等功能。这个小模块其实也可放在Common组件层,只是觉得这里面也有一些业务相关的功能,所以就放在了这一层。

当然,基础业务层还还包括APP设计风格中需要用到的各种动画,样式,颜色值,尺寸值等资源。在进行业务开发时,统一使用这些资源,为后续修改整个APP风格提供可能。

Common组件层

这里包含了一些通用的组件,包括各种常用的工具类,通用的UI库,数据源的封装(包括网络,文件,数据库)。这是一个APP的基本架构,里面包含的类基本不需要改动。所以在对工具类和通用UI进行定义时,需要考虑放置的位置是否准确。

以上是整个项目使用组件化/模块化后基本结构的详细介绍,但是在开发过程中还是遇到了很多问题。

遇到的问题

模式切换

从Android工程的结构可以看出,app模块和新建的其他Module的结构基本一致,最大的区别就是build.gradle的结构:

// app模块中build.gralde的结构:
apply plugin: ‘com.android.application’

// 其他Module中build.gralde的结构:
apply plugin: ‘com.android.library’

所以Module是否能够运行,关键就在于plugin的类型。将新建Module的build.gradle中的’com.android.library’ 改成 ‘com.android.application’,同步之后选择相应的模块运行即可。

所以模式的切换只需要根据条件进行判断即可,我们可在gradle.properties中定义一个常量,控制Module的运行模式:

gradle.properties中定义IS_MODULE:

IS_MODULE = false

然后在Module的build.gradle中添加条件判断:

if (IS_MODULE.toBoolean()) {
apply plugin: ‘com.android.library’
} else {
apply plugin: ‘com.android.application’
}

这样在进行模式切换时,只需要修改IS_MODULE的值即可。

AndroidManifest的合并问题

APP在进行打包时,会将所有依赖的Module中的AndroidManifest文件进行合并,具体的合并规则参考合并多个清单文件。合并最基本的原则:只能有一个Application配置了name属性,只能有一个Activity被配置成了主Activity。但是Module中如果不配置Applicaition中name属性,就不能进行相应的初始化,如果不指定主Activity,APP也无法运行。这里可使用两种方案来解决:

  • Module依然当做library使用,Module中的AndroidManifest也不需要指定Application的name属性和主Activity,直接加载Main模块(SplashActivity作为主Activity),在SplashActivity中动态修改要加载的模块。
  • 在Module中其他路径下新建一个AndroidManifest文件(其中为application标签指定了name属性,同时指定了主Activity),然后在build.gradle中根据IS_MODULE的值动态指定AndroidManifest的路径,这样Module在不同模式下使用不同的AndroidManifest文件就避免了合并出错的问题。但这种方案每个Module需要提供单独的Application类。

module/build.gradle

sourceSets {
main {
if (IS_MODULE.toBoolean()) {
manifest.srcFile ‘…/模块名/src/main/module/AndroidManifest.xml’
} else {
manifest.srcFile ‘…/模块名/src/main/AndroidManifest.xml’
}
}
}

如果选择了双AndroidManifest文件的方式,那么在作为Library的AndroidManifest(默认的)中组件的定义应尽量简单,包括主题都不要定义,这样合并时就很少出现合并错误。

如果在AndroidManifest.xml中定义了元数据,如极光推送:


那么除了在当前Module的build.gradle中定义JPUSH_CHANNEL和JPUSH_APPKEY:

manifestPlaceholders =[
JPUSH_PKGNAME : “com.sxu.library”,
JPUSH_APPKEY : “appkey”,
JPUSH_CHANNEL : “channel”
]

还需要在所有包含此Module的build.gradle中定义这两个常量,否则会出现manifest合并错误。

build.gradle的定义问题
引用Module问题

在引用可切换运行模式的Module时,要根据isModule的值动态添加依赖,如果isModule为true时,引用的模块是以Application的形式存在,此时引入时就会报错。

设置applicationId

applicationId属性在Application模式下才有效,所以在Module中设置时也需要添加isModule的条件判断。

依赖管理

cation的形式存在,此时引入时就会报错。

设置applicationId

applicationId属性在Application模式下才有效,所以在Module中设置时也需要添加isModule的条件判断。

依赖管理
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值