Android笔记:Android 组件化方案探索与思考

news2024/9/20 12:33:28

组件化项目,通过gradle脚本,实现module在编译期隔离,运行期按需加载,实现组件间解耦,高效单独调试。

先来一张效果图

img

组件化初衷

  • APP版本不断的迭代,新功能的不断增加,业务也会变的越来越复杂,维护成本高。
  • 业务耦合度高,代码越来越臃肿,团队内部多人协作开发困难。
  • Android项目在编译代码的时候电脑会非常卡,又因为单一工程下代码耦合严重,每修改一处代码后都要重新编译打包测试,导致非常耗时。
  • 方便单元测试,改动单独一个业务模块,不需要着重于关注其他模块被影响。

什么是组件化

组件化就是将一个app分成多个Module,如下图,每个Module都是一个组件(也可以是一个基础库供组件依赖),开发的过程中我们可以单独调试部分组件,组件间不需要互相依赖,但可以相互调用,最终发布的时候所有组件以lib的形式被主app工程依赖并打包成一个apk。

img

组件化优势

  • 组件化就是将通用模块独立出来,统一管理,以提高复用,将页面拆分为粒度更小的组件,组件内部除了包含UI实现,还包含数据层和逻辑层。
  • 每个工程都可以独立编译、加快编译速度,独立打包。
  • 每个工程内部的修改,不会影响其他工程。
  • 业务库工程可以快速拆分出来,集成到其他App中。
  • 迭代频繁的业务模块采用组件方式,业务线研发可以互不干扰、提升协作效率,并控制产品质量,加强稳定性。
  • 并行开发,团队成员只关注自己的开发的小模块,降低耦合性,后期维护方便等。

指导思想

  • 组件拆分:将一个project划分成业务组件、基础组件、路由组件。其中业务组件是相互隔离的,可以单独调试,基础组件提供业务组件所公用的功能,路由组件为业务组件之间通信提供支持。
  • 组件隔离:业务组件之间的隔离,可以单独调试。
  • 核心法则:编译期隔离,运行期按需依赖。

依赖关系

img

组件化需要考虑的问题

  • 模式切换:如何使得APP在单独调试跟整体调试自由切换
  • 资源冲突:当我们创建了多个Module的时候,如何解决相同资源文件名合并的冲突
  • 依赖关系:多个Module之间如何引用一些共同的library以及工具类
  • 组件通信:组件化之后,Module之间是相互隔离的,如何进行UI跳转以及方法调用
  • 入口参数:我们知道组件之间是有联系的,所以在单独调试的时候如何拿到其它的Module传递过来的参数

组件化后项目结构如下图

img

理论说了那么多,下面开始撸代码

实现步骤

1、全局设置Gradle,每一个业务Module需要的版本都定义在这里方便后期维护多个Module版本号

ext {
    // Sdk and tools
    minSdkVersion = 16
    targetSdkVersion = 26
    compileSdkVersion = 26
    buildToolsVersion = '26.0.2'
    supportLibraryVersion = '26.1.0'

    // App dependencies
    aRouter = '1.2.2'
    leakcanaryVersion = '1.3'
    glideVersion = '3.7.0'
}

 ####每个业务Module编译依赖版本
 compileSdkVersion rootProject.ext.compileSdkVersion
 buildToolsVersion rootProject.ext.buildToolsVersion
 minSdkVersion rootProject.ext.minSdkVersion
 targetSdkVersion rootProject.ext.targetSdkVersion

2、模式切换

组件化后的每一个业务的module都可以是一个单独的APP(isModuleRun=false), release 包的时候各个业务module作为lib依赖,这里完全由一个变量控制,在根项目 gradle.properties里面的 isModuleRun=true

isModuleRun状态不同,加载application和AndroidManifest都不一样,以此来区分是独立的APK还是lib, 实现方式如下 在build.grade里面配置

if (isModuleRun.toBoolean()) {
    apply plugin: 'com.android.application'
} else {
    apply plugin: 'com.android.library'
}

##单Module运行需要配置
sourceSets {
        main {
            if (isModuleRun.toBoolean()) {
                manifest.srcFile 'src/main/debug/AndroidManifest.xml'
            } else {
                manifest.srcFile 'src/main/AndroidManifest.xml'
                java {
                    //全部Module一起编译的时候剔除debug目录
                    exclude '**/debug/**'
                }
            }
        }
    }

3、资源冲突

业务Module和BaseModule资源文件名称重复会产生冲突,解决方案在 每个 module 都有 app_name,为了不让资源名重名,在每个组件的 build.gradle 中增加 resourcePrefix “xxx_强行检查资源名称前缀。 固定每个组件的资源前缀。但是 resourcePrefix 这个值只能限定 xml 里面的资源,并不能限定图片资源。 个人认为约定大于配置,团队内协定好规范,可以避免冲突。

4、组件通讯 组件通讯框架在github上有star最多的有ARouter和ActivityArouter,前者是个人项目,后者是阿里巴巴开源,权衡之下选择阿里的ARouter, 各业务Module之前不需要任何依赖可以通过路由跳转,完美解决业务之间耦合 使用方式如下。

 if (BuildConfig.DEBUG) {   // 这两行必须写在init之前,否则这些配置在init过程中将无效
           ARouter.openLog();     // 打印日志
           ARouter.openDebug();   // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
        }
ARouter.init(this); // 尽可能早,推荐在Application中初始化
compile "com.alibaba:arouter-api:$rootProject.aRouter"
每个业务Module都需要添加注解
annotationProcessor 'com.alibaba:arouter-compiler:1.1.3'

跳转方法 在目标Activity上添加path

@Route(path = ARouterManager.BModuleActivity)
public class BModuleActivity extends BaseActivity {
    @Autowired
    public String name;
    @Autowired(name = "age")
    int age;
    TextView txt;

    @Override
    protected int getLayoutId() {
        return R.layout.b_module_layout;
    }

    @Override
    protected void initView() {
        txt = findViewById(R.id.txt);
        //String name = getIntent().getStringExtra("name"); 也可以这样接受参数
        ARouter.getInstance().inject(this);
        txt.setText("name:" + name + ",age:" + age);

  #开始跳转
 btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 2\. 跳转并携带参数
                ARouter.getInstance().build(ARouterManager.BModuleActivity)
                        .withString("name", "888")
                        .withInt("age", 11)
                        .navigation();
            }
        });
/**
 * 路由管理类
 */

public final class ARouterManager {

    public static final String AFragment = "/amodule/AFragment";
    public static final String BFragment = "/bmodule/BFragment";
    public static final String CFragment = "/cmodule/CFragment";

    public static final String AModuleActivity = "/amodule/AAModuleActivity";
    public static final String BModuleActivity = "/bmodule/BModuleActivity";
    public static final String CModuleActivity = "/cmodule/CModuleActivity";

}

上述只使用了ARouter的简单用法,更多进阶用法请参考ARouter文档, ARouter

5、Application

当组件单独运行的时候,每个Module自成一个APK,那么就意味着会有多个Application,很显然我们不愿意重复写这么多代码,所以我们只需要定义一个BaseApplication即可,其它的Application直接继承此BaseApplication就OK了,BaseApplication里面还可定义公用的参数。

更多Android进阶指南 可以扫码 解锁 《Android十大板块文档》

1.Android车载应用开发系统学习指南(附项目实战)

2.Android Framework学习指南,助力成为系统级开发高手

3.2023最新Android中高级面试题汇总+解析,告别零offer

4.企业级Android音视频开发学习路线+项目实战(附源码)

5.Android Jetpack从入门到精通,构建高质量UI界面

6.Flutter技术解析与实战,跨平台首要之选

7.Kotlin从入门到实战,全方面提升架构基础

8.高级Android插件化与组件化(含实战教程和源码)

9.Android 性能优化实战+360°全方面性能调优

10.Android零基础入门到精通,高手进阶之路

敲代码不易,关注一下吧。ღ( ´・ᴗ・` ) 🤔

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1061568.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【多模态融合】TransFusion学习笔记(2)

接上篇【多模态融合】TransFusion学习笔记(1)。 从TransFusion-L到TransFusion ok,终于可以给出论文中那个完整的框架图了,我第一眼看到这个图有几个疑问: Q:Image Guidance这条虚线引出的Query Initialization是什么意思? Q:图像分支中的…

flex布局与几个实例(含源码)

本文简单的说明下flex布局 有源码实例,后续会持续添加 flex默认主轴是横轴 容器主要有6个属性 flex-direction 决定主轴的方向 flex-direction: row | row-reverse | column | column-reverse; flex-wrap 决定是否换行 flex-wrap: nowrap | wrap | wrap-revers…

JavaAPI---replace

package daysreplace;public class ReplaceTest {public static void main(String[] args) {String str "wwxhhhhhhhhhhh333";System.out.println("替换前的字符串" str);String newstr str.replace("333", "111");System.out.prin…

(第2遍中)内存的堆空间不够 error: MSB3073 超过了 PCH 的虚拟内存范围

压缩包里打开的新工程文件,运行 GenerateProjectFiles.bat 后,再点击 .sln 文件,编译工程,编译了 1.5h 左右,快结束的时候报错如下: 编译器的堆空间不足在第2遍中编译器的堆空间不足error MSB3073: 命令“…

【typescript】面向对象(下篇),包含接口,属性的封装,泛型

假期第八篇,对于基础的知识点,我感觉自己还是很薄弱的。 趁着假期,再去复习一遍 面向对象:程序中所有的操作都需要通过对象来完成 计算机程序的本质就是对现实事物的抽象,抽象的反义词是具体。比如照片是对一个具体的…

大恒IFrameData IImageData转bmp HObject Mat

大恒工业相机采集的帧数据转为其他8bit图像格式 C#转为bmp格式转为Halcon的HObject格式转为OpenCVSharp的Mat格式 回调采集图像的数据类型为IFrameData,单帧采集的数据类型为IImageData,两者的区别为IImageData类多了一个**Destroy()**方法 C# 转为bm…

floyd算法细节

这个不是一篇学习性文章 主要是针对这几天思考的问题进行一些回答 floyD在计网和数据结构和图模型中有广泛的应用算法 很简单但是其中蕴含的原理值得细究。 弗洛伊德算法(Floyd)主要针对多源最短路径,且可以解决路径中有负权的情况(不包含负权回路),但是迪杰斯特拉算法只…

mycat实现mysql读写分离

架构图: 视频地址

逐步解决Could not find artifact com:ojdbc8:jar:12

Could not find artifact com:ojdbc8:jar:12 in central (https://repo.maven.apache.org/maven2) 原因: ojdbc8:jar:12 属于Oracle 数据库链接的一个程序集,缺失的话很有可能会影响数据库链接,蝴蝶效应产生不可预测的BUG!但是版…

typescript开发环境搭建

typescript是基于javascript的强类型标记性语言,使用typescript语言可开发出不同规模的、易于扩展的web前端页面应用,本文主要描述typescript的开发环境搭建。 npm install -g typescript 如上所示,在本地开发环境中,使用nodejs…

arduino嵌入式1,LED闪烁案例

CVE系列在等等吧,环境我有点懒得搭建了 文章目录 前言一、anduino是什么玩意儿?二、使用步骤1.找蓝图/画蓝图2.写入数据成果 总结 前言 最近在学习嵌入式开发,我的单片机到了,然后我就沉迷于嵌入式开发的环境中 提示:…

1300*B. Sort the Array(排序构造)

题意: 一个无重复数字的序列,能否反转一个区间使其成为单增序列。 解析: 记录每个点的值和初始下标,然后排序。 对于排好序的序列进行遍历,找出第一段和原序列下标不同的区间并且标记(此区间即为翻转的区…

SpringCloud Alibaba - Seata 四种分布式事务解决方案(XA、AT)+ 实践部署(上)

目录 一、Seata 分布式事务解决方案 1.1、XA 模式 1.1.1、XA模式理论 第一阶段: 第二阶段: 1.1.2、Seata 框架中的 XA 模式 第一阶段: 第二阶段: 1.1.3、XA 模式的优缺点 1.2.4、实现Seata 的 XA 模式 a)修改…

建筑施工行业招投标资源众包分包系统站点开发

一款针对建筑、施工行业开发的程序系统平台,运营方可以招募企业发布招投标信息以及招聘信息。 核心功能:一、项目招投标众包发布和投标 企业可以根据自身资源或者实际需求发布参与招投标信息,程序后台可以管理、审核用户发布的信息。参与招…

【C++】AVL树 红黑树

AVL树 AVL树也是二叉搜索树的一种。因为对于普通的二叉搜索树,当插入的数据在有序或接近有序的情况下,二叉搜索树很可能退化成单支树,导致查找效率低下。而AVL树就很好的解决了这个问题。 首先,AVL树是一棵二叉搜索树。同时对于A…

appscan的两种手动探索扫描方式

文章目录 一、使用火狐FoxyProxy浏览器代理探索二、使用appscan内置浏览器探索 一、使用火狐FoxyProxy浏览器代理探索 首先火狐浏览器需安装FoxyProxy 先在扩展和主题里搜FoxyProxy 选FoxyProxy Standard,然后添加到浏览器就行 添加后浏览器右上角会有这个插件 打开apps…

JVM篇---第三篇

系列文章目录 文章目录 系列文章目录一、什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”?二、Java内存结构三、说说对象分配规则一、什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文…

Maven 中引用其他项目jar包出现BOOT-INF问题

问题 在B项目中引入A项目的类,但是发现怎么也引入不进来 A项目打包之后,想在B项目中引用jar 在B项目中发现类文件无法引用 参考网上进行清缓存等一系列操作都没有解决。 最后发现引用的jar包中包含BOOT-INF, 然后去A项目中查找&#xff…

云原生边缘计算KubeEdge安装配置

1. K8S集群部署,可以参考如下博客 请安装k8s集群,centos安装k8s集群 请安装k8s集群,ubuntu安装k8s集群 2.安装kubEedge 2.1 编辑kube-proxy使用ipvs代理 kubectl edit configmaps kube-proxy -n kube-system #修改kube-proxy#大约在40多行…

【动手学深度学习-Pytorch版】Transformer代码总结

本文是纯纯的撸代码讲解,没有任何Transformer的基础内容~ 是从0榨干Transformer代码系列,借用的是李沐老师上课时讲解的代码。 本文是根据每个模块的实现过程来进行讲解的。如果您想获取关于Transformer具体的实现细节(不含代码)可…