前言
我一直把我的毕设项目【小鹅事务所】当成日常记账原本使用。
可是最近总觉得厌烦了,它的功用都符合我的需求,总觉得差点什么。打开代码一看,金玉在外,败絮其中。看看他人家的NowInAndroid,是如此的高雅。
表面上我还在用着。可是内心已经暗下决心,要把小鹅事务所重构成NIA的样子,它才是我心目中的Android最佳实践。
项目架构重构
首先要着手重构的当然是项目架构。小鹅事务所的架构是这样的:
包括3个模块,CalendarView日历模块来源于开源项目。实际上其实一切使用代码都写在了app模块中,也便是一个单模块的项目,app模块中又包括了记事本、记账本、事务、纪念日的代码耦合在一起。
它的优点便是写起来很爽。可是这不可啊,你看看他人NIA分为十几个模块井井有条,有鼻子有眼的。我这个就悉数挤在一团,丑死了。所以我打算把不同的模块先抽出来弄成这个样子。
刚开端开工,我又犯难了,项目依靠SDK的时分悉数写在dependencies里的。假如要挪成不同的模块,第一个需求解决的便是依靠版本的统一。
VersionCatalogs
在NIA项目中有一个libs.version.toml
文件管理依靠,它的官方文档是这个docs.gradle.org/current/use…。
If a
libs.versions.toml
file is found in thegradle
subdirectory of the root build, then a catalog will be automatically declared with the contents of this file.
也便是说只要新建一个libs.version.toml
文件到gradle文件夹中,就会主动生成一个VersionCatalogs,能够直接在依靠的时分拿来用。
这种方式太高雅了,这小代码写的可真够俏。
为什么在plugins无法辨认出现爆红呢?所以我看了一下NIA,也有这个问题,他们是加了一个注解@Suppress("DSL_SCOPE_VIOLATION")
解决的,而且注释了一个链接,有兴趣能够看看。youtrack.jetbrains.com/issue/KTIJ-…
Plugins
上面截图中出现的id(xxx.android.library)
其实便是使用了Gradle的注册Plugin的功用,只需求在build-logic
中的build.gradle
注册就能够了,就能够在编译的时分主动运行履行Plugin类的逻辑,而这个Plugin类能够自界说。
gradlePlugin {
plugins {
register("androidApplicationCompose") {
id = "nowinandroid.android.application.compose"
implementationClass = "AndroidApplicationComposeConventionPlugin"
}
...
}
}
class AndroidApplicationComposeConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
pluginManager.apply("com.android.application")
val extension = extensions.getByType<ApplicationExtension>()
configureAndroidCompose(extension)
}
}
}
在Kotlin类中写Gradle编译代码,还有代码联想,这多是一件美事啊,编译代码还能够互相复用,例如下面的configureAndroidCommon
函数。
build-logic复合构建
上文中经常出现build-logic
,它的作用其实和buildSrc
类似,用来界说编译脚本的。上文的Plugin就能够写在这个项目中。
与buildSrc
不同,它是一个独立的Gradle项目,不依靠当时项目,也便是说能够独立编译。所以它就享受不到主动生成的VersionCatalogs了,怎样办呢?
官方文档写得很明确,能够在另一个项目的settings.gradle.kts
中找到指定文件显式去生成。
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
关于build-logic
的削减重复构建、削减构建时间的之类优点就不细说啦。
分模块
到这儿总算能够将app模块的代码抽出来分红多个模块了,由于我写了许多Plugin插件,所以在新建模块的时分就能够很好的复用了,举个比如我想弄一个home模块,build.gradle.kts
能够写成这样。
剩下的就只有挪代码、挪代码和处理爆红代码的工作了,十分单调。
就像整理一个杂乱无章杂乱无章的房间那样。一开端会干劲十足,等做到后面会渐渐开端泄气。我怎样写了这么多东西,这些代码为什么耦合度会这么大,此刻我还没意识到,这仅仅只是一个开端。
View替换成Compose
我刚做这个毕设项目的时分,Compose刚出1.0稳定版。
我说:我要用全Compose来写UI界面,是不很大胆。
我将这个全Compose方案告诉我的其他同学,他们都很振奋。
我说:只用三周,一周学习,一周编写代码,一周改BUG就能够写完这个项目。
国内很少资料,我参阅了许多国外的资料,Compose实在太酷了。
通过一年多对Compose的研讨和实践,我发现我还是忘不了这个方案,我很想把小鹅事务所变成Compose的容貌。
规划
既然当初用的Material2来规划小鹅事务所,那现在,我就要用Material3规划,还要加入Android12最新的动态配色!
所以我打开了Figma,刚想来一场酣畅淋漓的规划。后来我想想,规划稿的用途是规划用来和开发对接的产物。而我既是规划也是开发,规划稿就变成了一个可有可无的东西。
Compose代码编写
刚开端将View换成Compose的时分,我十分振奋,总算能够大规划地实践Compose了。我所以把代码写得十分规范,甚至在控件中加上Preview
。常常写完一个控件,就美美把之前的View和Layout文件删去。
当这项工作进行到一半的时分,我发现之前的UI界面许多,有的写得十分高雅,有的写得有点乱。每一行代码都牵引出我的回忆,有种帮同居目标搬走这个屋子的感觉。
渐渐地删去旧代码带来的剥离感让我陷入了深思,我是不是一开端就不应该开端这项重构工作,将就将就也不是不能用。可是Compose带来的新鲜感让我无法拒绝。
在不断自我拉扯中,我潦草地完结了这些工作,Preview也不写了,代码也不那么高雅了。
在重构完结之际,我决定留下了这几行代码作为纪念。
思考
小鹅事务所的重构一期工作暂时告一段落,花了3个多月,依然没有重构到NIA那般样子。
我在工作中也不断接触Android项目,有的项目在使用Java,许多项目依然使用曩昔的架构、架构、规划模式。当Android最佳实践不断推陈出新的时分,不是一切项目都能跟得上。我这么一个小项目略微重构一下都需求花上几个月时间,而大项目是几乎不可能像这样大规划重构的,这得花多少时间啊…这就造成了一个成规划的项目无法真实追赶上谷歌所谓的“最佳实践”。
Android的最佳实践只是一种抱负,在前史代码和程序员考核面前,它似乎一文不值。
代码
最后放一下重构之后的代码库房: github.com/MReP1/Littl…