android 构件组件,Android 组件化

本文详细介绍了Android业务组件化的实施步骤和优势,包括模块开发模式切换、数据路由、资源管理和代码隔离等方面。通过组件化,可以提高开发效率,降低耦合性,便于后期维护。然而,也面临着模块间数据交换的挑战和路由器的成熟度问题。作者提出了使用ARouter进行解耦,并分享了解决Butterknife注解问题的方法。此外,还讨论了在fragment中处理onActivityResult的策略。

前言

随着业务的增多,迭代版本的增加,

模块化开发, 业务解耦, 业务独立进行测试,编译,运行,想想都惊喜~

如果不想忍受超长的编译时间,不想忍受类之间的强耦合,受够了满屏的不相干的文件,那么.....

为了你的"代码洁癖",还有项目的未来, 组件化, 势在必行.....

Android 业务组件化

类似于UML类图中聚合的概念,如下图所示,

bb30c31de505?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

组件可以自己行动,也可以组成一个整体运行.

关于基础组件,可以同时放在一个base包下, 也可以将base分不同的包,比如 数据库lib, 资源lib,等等...这些其实可以自己定义.

优点

便于开发,团队成员只关注自己的开发的小模块,降低耦合性,后期维护方便等。各自可以按照自己的代码风格开发,最后组装,成一个 app。

每个模块都可以打包成一个带版本号的@aar,对业务进行版本控制,降低了修改某一个业务造成其他业务受影响的风险.

与插件化的风险比较,组件化是几乎没有风险的,当下就可以做的一种架构.

不足

在模块间 数据交换,相互依赖,可能存在难题,路由器模块还不太成熟,问题各不相同,需要各自解决.

SHOW

bb30c31de505?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

zujianhua.gif

模块化 会遇到如下问题

libarary和applicaiton 之间的转换

路由器,如何在拿不到类名的情况下,启动,模块间相互吊起服务. 最近路由器很多~

目前的路由有阿里巴巴的,

还有mzule的ActivityRouter.

代码解耦,作为线程间交互桥梁. 我用的是eventBus,作为事件总线,代替handler,

在集合app的最后,将每个模块打包成aar,减少编译时间.

组件化的构建步骤

bb30c31de505?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

1. 模块开发模式切换

1.在gradle.properties 增加一个变量

# true代表模块开发,false代表合并到主app.

#模式切换开关

isModule=false

2.在每个业务module的build.gradle里面添加

//根据isModule值进行切换 是否为lib或者app

if (isModule.toBoolean()) {

apply plugin: 'com.android.application'

} else {

apply plugin: 'com.android.library'

}

3.建立两个AndroidManifest.xml,进行切换

大家都知道,当项目是APPlication时候,需要有category为LAUNCHER的入口activity.

而当项目是lib的时候,不能存在入口activity.所以要分别建立两套AndroidManifest.xml,还要注意,如果想要保持主题样式通用, 主app项目下的theme,'ico','label'等等,在module中都不能存在.

进行如下配置.

bb30c31de505?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

4.建立两个AndroidManifest.xml,进行切换

sourceSets {

main {

if (isModule.toBoolean()) {

manifest.srcFile 'src/main/AndroidManifest.xml'

} else {

manifest.srcFile 'src/main/release/AndroidManifest.xml'

java {

//release 时 debug 目录下文件不需要合并到主工程

exclude '**/debug/**'

}

}

}

}

5.业务组件不需要混淆代码.

一旦业务组件的代码被混淆,而这时候代码中又出现了bug,将很难根据日志找出导致bug的原因;

6.当ismodule开关为true时,每个module可独立运行.

bb30c31de505?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

2. 数据路由

首先,考虑到解耦, 可以把ARouter的所有跳转都进行封装.以防以后更换路由器.

这里,module内,可以用传统方式传递和用路由器传递都行.

3. 资源重复

module1和module2都依赖base,则gradle在编译期间,会自动去重,我们不需要管.

资源名重复,解决1:在编码的时候 添加resourcePrefix "video"+"_",强制人员添加前缀(但是对drawable不支持,需用户自己增加前缀).

解决2:将资源统一放在一个module(比如Base中),但是编译会增加时间.(不太复合资源解耦 原则)

如果是用provide代替complile

4. 代码隔离-(面向接口编程)

基础库Base

网络库 我们项目用的volley(10年开始的项目迭代至今),

资源库 基础mipmap,drawable资源等等

BaseClass BaseActivity,BaseBean,BaseAdapter等等.

weight组件 共同的自定义view,或者第三方view.

....

组件Module

组件间通信 IProvider

请参考ARouter的文档的通过依赖注入解耦:服务管理(一) 暴露服务 进行~

举个例子, 在我的项目中clean-project-architecture中,videoModule的拍照功能需要调用loginmodule的登录功能,按照上述例子,就可以实现.

// 声明接口,其他组件通过接口来调用服务

/**

* 示例:子模块间调用方法

* Created by chenchangjun on 17/8/14.

*/

public interface LoginModuleService extends IProvider {

boolean checkLoginState();

}

// 实现接口

/**

* * 实现接口,

* Created by chenchangjun on 17/8/14.

*/

@Route(path = RouterConstants. LOGIN_SERVICE_IMPL)

public class CheckLoginService implements LoginModuleService{

/**

* 实例化服务,面向接口编程

* @return

*/

@Override

public boolean checkLoginState() {

//可自行在loginModule

return false;

}

@Override

public void init(Context context) {

}

}

//另外一个module调用,(由接口进行隔离)

private void takePhoto() {

if (loginModuleService.checkLoginState()){ //模拟模块间通信,调用登录服务:如果登录就开始下一步.

startTakePhoto();

}else {

Toast.makeText(this,"请登录",Toast.LENGTH_SHORT).show();

}

}

宿主App

每个module都有Application ,这里,为了方便, 将共同的东西抽取出来,放在了basemodule的BaseApplicaiotn中.

当遇到每个module可能都要有自己初始化的方法,我们可以在每个module 附带一个application.

遇到问题

1.Butterknife 的bindview()方法,library的不能存在,原因是在app和library切换的时候,注解上的变量必须是static final, library不能存在switch().

问题:

bb30c31de505?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

解决

上述问题可以,将R改为R2如上图第二个变量所示.重新clean,即可.

butterknife的onclick事件,用下面的方式处理即可.

注解问题,就像用dragger.xutils等等,能不能这种方式处理,还有待测试.

//package com.ccj.login.ui.login;

/**

* click方法中同样使用R2,但是找id的时候使用R,

* ibrary中是不能使用 switch- case 找id的,原因:http://www.jianshu.com/p/89687f618837

*/

@OnClick({R2.id.iv_cancel, R2.id.btn_login, R2.id.btn_register})

public void onClick(View view) {

int i = view.getId();

if (i == R.id.iv_cancel) {

finish();

} else if (i == R.id.btn_login) {

//mPresenter.login(tvPhone.getText().toString(), tvPassword.getText().toString());

Toast.makeText(this,"登录测试",Toast.LENGTH_SHORT).show();

} else if (i == R.id.btn_register) {

navigateToRegister();

}

}

2.目前,路由器ARouter 没有解决onActivityResult的fragment分发问题.

问题:

当你再fragment上 进行路由

ARouter.getInstance().

build(RouterConstants.VIDEO_MUDULE_ACTIVITY).

withString(Constants.START_LOGIN_WITH_PARAMS, "I am params from MainActivity").

navigation();

在fragment中的onActivityResult是接收不到数据的,ARouter会在activity中调用该方法.

解决

在BaseActivity中重写onActivityResult方法.让子类继承即可.

/**

* 解决fragment onActivityResult不调用

*

* @param requestCode

* @param resultCode

* @param data

*/

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

FragmentManager fm = getSupportFragmentManager();

//if (index != 0) {

if (fm.getFragments() == null) {

Log.w(TAG, "Activity result fragment fragmentIndex out of range: 0x"

+ Integer.toHexString(requestCode));

return;

}

for (int i = 0; i

Fragment frag = fm.getFragments().get(i);

if (frag == null) {

Log.w(TAG, "Activity result no fragment exists for fragmentIndex: 0x"

+ Integer.toHexString(requestCode));

} else {

handleResult(frag, requestCode, resultCode, data);

}

}

return;

//}

}

/**

* 递归调用,对所有子Fragement生效

*

* @param frag

* @param requestCode

* @param resultCode

* @param data

*/

private void handleResult(Fragment frag, int requestCode, int resultCode,

Intent data) {

frag.onActivityResult(requestCode, resultCode, data);

List frags = frag.getChildFragmentManager().getFragments();

if (frags != null) {

for (Fragment f : frags) {

if (f != null)

handleResult(f, requestCode, resultCode, data);

}

}

}

3 各种编译处理插件,可能会出现问题

因为Arouter是编译期间 执行,所以当你的项目集成dragger2,butterknife,xutils,databinding可能会出现问题.需要各自排查

总结

组件化是用gradle作为组间切换工具,用Arouter作为跳转路由器 的一种 框架.

在开发中, 组件化,有利于模块业务解耦,让每人负责的业务相互独立.

在后续开发中,我们可以将不同的组件模块lib分别独立,需要的时候分别进行依赖即可.

参考:

本实践项目深入研究了基于C#编程环境与Halcon图像处理工具包的条码检测技术实现。该原型系统具备静态图像解析与动态视频分析双重功能,通过具体案例展示了人工智能技术在自动化数据采集领域的集成方案。 C#作为微软研发的面向对象编程语言,在Windows生态系统中占据重要地位。其语法体系清晰规范,配合.NET框架提供的完备类库支持,能够有效构建各类企业级应用解决方案。在计算机视觉技术体系中,条码识别作为关键分支,通过机器自动解析商品编码信息,为仓储管理、物流追踪等业务场景提供技术支持。 Halcon工具包集成了工业级图像处理算法,其条码识别模块支持EAN-13、Code128、QR码等多种国际标准格式。通过合理配置检测算子参数,可在C#环境中实现高精度条码定位与解码功能。项目同时引入AForge.NET开源框架的视频处理组件,其中Video.DirectShow模块实现了对摄像设备的直接访问控制。 系统架构包含以下核心模块: 1. Halcon接口封装层:完成图像处理功能的跨平台调用 2. 视频采集模块:基于AForge框架实现实时视频流获取 3. 静态图像分析单元:处理预存图像文件的条码识别 4. 动态视频解析单元:实现实时视频流的连续帧分析 5. 主控程序:协调各模块工作流程 系统运行时可选择图像文件输入或实时视频采集两种工作模式。识别过程中将自动标注检测区域,并输出解码后的标准条码数据。该技术方案为零售业自动化管理、智能仓储系统等应用场景提供了可靠的技术实现路径,对拓展计算机视觉技术的实际应用具有重要参考价值。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
Java内存泄漏发现技术研究.pdf内容概要:本文围绕Java内存泄漏的发现技术展开研究,针对现有研究多集中于泄漏发生后的诊断与修复,而缺乏对泄漏现象早期发现方法的不足,提出了一套结合动态与静态分析的综合解决方案。动态方面,设计了一种面向泄漏的单元测试生成方法,通过识别高风险泄漏模块并生成具有泄漏检测能力的单元测试,实现早期泄漏发现;静态方面,提出基于模式的检测方法,重点识别因错误使用WeakHashMap等弱引用结构导致的内存泄漏,通过静态扫描源代码提前发现潜在缺陷。系统基于JUnit、CodePro Analytix和Soot等工具实现,实验验证了其在JDK等开源项目中发现已知泄漏缺陷的能力。; 适合人群:具备一定Java编程基础,从事软件开发、测试或质量保障工作1-3年的研发人员,以及对程序分析、内存管理感兴趣的研究生或技术人员。; 使用场景及目标:①帮助开发者在编码和测试阶段主动发现潜在内存泄漏,提升软件健壮性;②为构建自动化内存泄漏检测工具链提供理论与实践参考;③深入理解Java内存泄漏的常见模式(如WeakHashMap误用)及对应的动态测试生成与静态分析技术。; 阅读建议:建议结合Soot、JUnit等工具的实际操作进行学习,重点关注第三章和第四章提出的三类泄漏模块识别算法与基于模式的静态检测流程,并通过复现实验加深对溢出分析、指向分析等底层技术的理解。
本方案提供一套完整的锂离子电池健康状态评估系统,采用Python编程语言结合Jupyter交互式开发环境与MATLAB数值计算平台进行协同开发。该技术框架适用于高等教育阶段的毕业设计课题、专业课程实践任务以及工程研发项目。 系统核心算法基于多参数退化模型,通过分析电池循环充放电过程中的电压曲线特性、内阻变化趋势和容量衰减规律,构建健康状态评估指标体系。具体实现包含特征参数提取模块、容量回归预测模型和健康度评估单元三个主要组成部分。特征提取模块采用滑动窗口法处理时序数据,运用小波变换消除测量噪声;预测模型集成支持向量回归与高斯过程回归方法,通过交叉验证优化超参数;评估单元引入模糊逻辑判断机制,输出健康状态百分制评分。 开发过程中采用模块化架构设计,数据预处理、特征工程、模型训练与验证等环节均实现独立封装。代码结构遵循工程规范,配备完整注释文档和单元测试案例。经严格验证,该系统在标准数据集上的评估误差控制在3%以内,满足工业应用精度要求。 本方案提供的实现代码可作为研究基础,支持进一步功能扩展与性能优化,包括但不限于引入深度学习网络结构、增加多温度工况适配、开发在线更新机制等改进方向。所有核心函数均采用可配置参数设计,便于根据具体应用场景调整算法性能。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值