现代化 Android 开发:组件化与模块化的抉择

这篇具有很好参考价值的文章主要介绍了现代化 Android 开发:组件化与模块化的抉择。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

作者:古哥E下

项目初始的时候,一般都是使用一个分层架构,接入各种框架,然后就写业务代码。但如果项目慢慢变大,那就会出现很多项目管理的问题,诸如:

1.代码复用与抽象问题
2.编译速度问题
3.版本迭代速度问题

所以组件化、模块化、动态化、插件化、跨平台等各种技术就会被提及被重视。

组件化

我们已经度过了洪荒时期的 Android 开发,因为官方已经给出了非常优秀的 Jetpack 组件库,所以我们目前更多的是制作业务型的组件与抽象,去解决某一类场景或者大家都可能用到而写起来又繁琐又容易出错的场景。

写组件也不是一件容易的事情。

首先,开发组件得意识到某些场景是可以抽象的,如果抱着代码能跑起来就行了的态度去编程,那基本不可能想到去抽象的,也是最容易陷入代码陷阱无法自拔的。即使是最简单的抽取,很多时候也是宁愿不厌其烦的复制粘贴,也不愿意去抽取一个公共方法。然后等别人开发出了组件后,除了感叹真香,也就没什么其它感悟了。

其次,开发组件得设计出好用而简洁的 API,很多童鞋,除了数据实体类和各种 Manager 类,基本不会再定义新的数据结构了,就更别提设计接口供其它人使用了。

然后,开发组件得想好组件的配置,提升组件的灵活性,产品最喜欢复用以前的逻辑而再加上一点点的不同,如果不能够配置,那组件的局限性就大打折扣了。

最后,开发组件还得做好边缘情况的处理、异常的处理。组件会被各种人以各种姿势调用,所以各种想不到的场景都有可能出现,这也考验开发写代码对细节的把控。

所以我一直重视的是写组件的能力,是需要不断的训练的,也是需要不断的阅读优秀的组件库去掌握的。面试必问 Okhttp 的拦截器,可以你有真正在自己的组件里使用过类似的东西吗?

最举个例子? 假设现在我们要用 AudioRecord 写一个录制功能。最开始那可能直接在 Activity 里开撸了:

private var isRecording = false;
private suspend fun startRecording() {
    audioRecord = AudioRecord(...)
        
    val data = ByteArray(bufferSize)
    audioRecord.startRecording()
    isRecording = true
    File(applicationContext.filesDir, "recording.pcm").outputStream().use {outputStream ->
        while (isRecording) {
            val bytesRead = audioRecord.read(data, 0, bufferSize)
            if (bytesRead > 0) {
                outputStream.write(data, 0, bytesRead)
            }
        }
    }
    audioRecord.stop()
    audioRecord.release()
}

这样写下来,流程一通,然后就觉得大功告成了。
然后产品逻辑就变更了:要把音频数据实时上传到服务器。

改:把写文件的部分换成网络传输

过一会儿,老板又找来了,在没网络的时候录制就失败了,这不行,要在无网络的时候录制到本地。

改:判断下网络环境,加 if else 。

过一会儿,老板又找来了,我开始有网络,但是进入电梯后录制就失败了,所以一定要保存一份到文件中,如果有网络,那也往网络写一份。

改:从 if else 逻辑换成双写逻辑。

只针对上面的场景,整体流程是相当稳定的,只是写入的目标地不一样,那为何不抽象一个 AudioSink 的接口来表示写入的存储目标?

interface AudioSink {
    suspend fun write(buf: ByteArray, offset: Int, len: Int)
    fun close()
}

那整个流程就稳定为:

private suspend fun startRecording(sink: AudioSink) {
    audioRecord = AudioRecord(...)
        
    val data = ByteArray(bufferSize)
    audioRecord.startRecording()
    isRecording = true
    while (isRecording) {
        val bytesRead = audioRecord.read(data, 0, bufferSize)
        if (bytesRead > 0) {
            sink.write(data, 0, bytesRead)
        }
    }
    audioRecord.stop()
    audioRecord.release()
    sink.close()
}

如果要写文件,写个实现:

class FileAudioSink(file: File): AudioSink {
    ...
}

如果要写网络,写个实现:

class NetworkAudioSink(api): AudioSink {
    ...
}

如果要判断本地与网络,就写个代理:

class DelegateAudioSink(
    val origin: AudioSink
): AudioSink {
    ...
}

如果要同时写本地与网络,就是双写或多写:

class MultiAudioSink(
    val list: List<AudioSink>
): AudioSink {
    ...
}

这些类一写,那具体逻辑就是入口传参的变更了。当然实际情况应该考虑各种异常情况。如果你足够有经验,那在一开始就能把这些场景考虑到,并且把其用处和局限性同步给产品,帮助产品一开始做出最优选择。这才是所谓的经验。

如果回头来看上面的例子,发现都是很熟悉的东西,说是设计模式也行。如果将整个抽象做好,如果从音频切换到视频,那是否这一块可以完美复用?那是不是就可以更早的完成需求?——然后就可以更早的被裁掉~

组件化,就是对业务场景、功能场景的抽象。这是最需要大家去投入时间去做、去训练的。

模块化

一些复杂的组件,本身就可以构成一个个的模块,然后单独出来维护。但在谈论模块的时候,更多的是谈论业务模块。就是把不同业务放在不同的模块下。这对于巨型 App, 其意义当然是有的,毕竟可能是一个团队维护某一个模块。而对于小 App, 那意义就不是特别大了。

因为模块化会带来非常棘手的问题:模块之间的通信问题。Arouter、TheRouter 都很大程度上是为了解决模块间的通信问题。而简单的模块化一般是考虑基础模块的抽取,但基础模块的定义总是模糊的,不经意间就抽取出一个巨无霸的基础模块。就跟很多喜欢用 Base 类的同学,最后就一个巨大的 Base 类。

所以一般小的 App, 搞模块化是大可不必的。巨型 App 是存在编译速度、多团队开发的问题,所以各大公司都会出品和分享自己的多模块化实践。小公司就容易跟风把工程搞得巨复杂,这就没意思了。

例如大公司拆分多模块,然后用 aar 包来加速构建速度,相对应的有私有 Maven 仓库,自动打包脚本,搞得很是复杂,对他们而言是很有必要。而对于小公司,其投入产出比,还不如花点钱,买台好一点的电脑来得香。

动态化、插件化

对于动态化和插件化,我只能感叹下,写出这些框架的大佬们,技术是真的强,都是真正的黑客。大概也只有国内的巨型 App 和奇怪的市场审核逻辑才能造就出这些需求。

有时间的话,看看这些库的源码也是很不错的,很涨见识。重要的还是看各大框架遇到的问题场景,以及是如何探索解决方案,最终是如何解决的。

不过问题始终是维护问题,随着 Android 版本的迭代,总归是需要有新的改动或者需要寻求新的方案,但国内的框架和库的成功往往和推动这个项目的人有关,没有一个稳定维护的机制,很容易受到人员变动的影响。

最后

再复杂的东西,也是由一个个的零件慢慢组装起来的。我们要有蓝图,然后为实现这个蓝图而拧螺丝。拧得多了,也许就有机会拧更大的螺丝。我在 emo 组件库上拧了 20 个螺丝,拧得多了,也算是一个不小的库了。不过目前我源码已经转 private 了,后面拧的螺丝,只想留给小团体孤芳自赏了。用行动证明一下,国内的开发者的开源库是多么的不稳定。

Android 学习笔录

Android 性能优化篇:https://qr18.cn/FVlo89
Android 车载篇:https://qr18.cn/F05ZCM
Android 逆向安全学习笔记:https://qr18.cn/CQ5TcL
Android Framework底层原理篇:https://qr18.cn/AQpN4J
Android 音视频篇:https://qr18.cn/Ei3VPD
Jetpack全家桶篇(内含Compose):https://qr18.cn/A0gajp
Kotlin 篇:https://qr18.cn/CdjtAF
Gradle 篇:https://qr18.cn/DzrmMB
OkHttp 源码解析笔记:https://qr18.cn/Cw0pBD
Flutter 篇:https://qr18.cn/DIvKma
Android 八大知识体:https://qr18.cn/CyxarU
Android 核心笔记:https://qr21.cn/CaZQLo
Android 往年面试题锦:https://qr18.cn/CKV8OZ
2023年最新Android 面试题集https://qr18.cn/CgxrRy
Android 车载开发岗位面试习题:https://qr18.cn/FTlyCJ
音视频面试题锦:https://qr18.cn/AcV6Ap文章来源地址https://www.toymoban.com/news/detail-511638.html

到了这里,关于现代化 Android 开发:组件化与模块化的抉择的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 云原生微服务:现代化应用开发的支柱

    云原生微服务是一种创新的应用架构模式,它结合了云计算和微服务架构的最佳实践。本文将介绍云原生微服务的定义、特点和优势,并探讨它在现代化应用开发中的重要性和应用。 在当今数字化时代,企业面临着日益复杂的应用开发挑战。传统的单块应用已经无法满足快速

    2024年01月19日
    浏览(54)
  • 一篇读懂 Android 开发中模块化、组件化、插件化和热修复

    网上关于 “Android 开发\\\" 的文章很多,我本人学习 Android 开发的过程也借鉴了网上先辈们的文章;但大多数文章都从底层的细枝末节开始讲述,由下而上给人一种这门技术“博大精深”望而生畏的感觉;而我写这篇文章的初衷就是由上而下,希望别人在阅读的过程中能够觉得

    2023年04月08日
    浏览(30)
  • Vue.js 3 项目开发:迈向现代化前端开发的必经之路

    随着前端技术的不断发展,Vue.js作为一种轻量级的JavaScript框架,已经逐渐成为了前端开发者的首选。Vue.js 3有哪些新特性、优势以及如何高效地进行项目开发呢? Vue.js是一种用于构建用户界面的渐进式框架。它的核心库专注于视图层,易于与其他库或现有项目集成。Vue.js 3是

    2024年01月23日
    浏览(40)
  • Python使用pywebview开发桌面应用:打造现代化、跨平台的用户体验

    📚 个人网站:ipengtao.com 在当今科技快速发展的时代,为了提供更好的用户体验,许多应用程序都转向了桌面应用的开发。在Python领域, pywebview 是一款优秀的库,它使得用Web技术开发桌面应用变得轻而易举。本文将深入探讨如何使用 pywebview 创建现代化、跨平台的桌面应用,

    2024年02月04日
    浏览(38)
  • 【JavaScript精通之道】掌握数据遍历:解锁现代化遍历方法,提升开发效率!

    ​ 🎬 岸边的 风 :个人主页  🔥  个人专栏  :《 VUE 》 《 javaScript 》 ⛺️  生活的理想,就是为了理想的生活 ! ​ 目录  📚 前言  📘 1. reduce方法 📘 2. forEach方法 📘 3. map方法  📘 4. for循环 📘 5. filter方法 📘 6. for...of循环 📘 7. Object.keys方法 📘 8. Object.values方法 📘

    2024年02月10日
    浏览(32)
  • Java Web现代化开发:Spring Boot + Mybatis + Redis二级缓存

    Spring-Boot因其提供了各种开箱即用的插件,使得它成为了当今最为主流的Java Web开发框架之一。Mybatis是一个十分轻量好用的ORM框架。Redis是当今十分主流的分布式key-value型数据库,在web开发中,我们常用它来缓存数据库的查询结果。 本篇博客将介绍如何使用Spring-Boot快速搭建一

    2024年01月17日
    浏览(42)
  • Android 组件化○

    1.组件化 组件化是指解耦复杂系统时,将多个功能模板拆分、重组的过程。在Android工程表现上就是把app按照其业务的不同,划分为不同的Module。 组件化架构的目的就是让每个业务模块变得相对独立,各个组件在组件模式下可以独立开发调试,集成模式下又可以集成到“app壳

    2023年04月20日
    浏览(68)
  • Wisej.NET 3.2.3 Crack 商业应用程序的Web开发构建迁移现代化工具

    Wisej.NET 3.2 adds new enterprise-grade features that simplify the development of complex Line of Business (LOB) cloud applications for the enterprise. Our goal is always to help improve developers productivity and make the applications using Wisej.NET more resilient and maintainable.   Getting Started The latest Wisej.NET 3.2 is available on NuGet. To use

    2024年02月16日
    浏览(54)
  • Day956.代码现代化 -遗留系统现代化实战

    Hi,我是 阿昌 ,今天学习记录的是关于 代码现代化 的内容。 代码现代化的主要模式。 大体的脉络是这样的: 先对代码做可测试化重构,并添加测试; 在测试的保护下,安全地重构; 在测试的保护下,将代码分层。 先来看看 如何让代码变得可测 ,这是遗留系统现代化的

    2024年02月01日
    浏览(121)
  • Android 架构 - 组件化 Componentization

    组件化是基于可重用目的,对单个功能进行开发,提升复用性降低耦合度。多个功能组件起来就是一个业务组件,多个业务组件组合起来就是一个应用,因此去除了模块间的耦合,使得按业务划分的模块成了可单独运行的业务组件。(组件化只是一定程度上的独立,还是依附

    2024年01月16日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包