每天一个干货小贴士,记录学无止境的足迹
在 Java 时代,处理资源(比如读写文件、数据库 Cursor)是一件很痛苦的事,因为最后必须要放在 finally 块里手动 close()。一旦忘记关“水龙头”,就会造成内存泄漏(水漫金山啦!)。
在 Kotlin 里,任何实现了 Closeable 或 AutoCloseable 接口的对象(比如 File、Stream、Cursor、Socket),都可以直接调用 .use {}!
FileReader("test.txt").use { reader ->
// 在这个大括号里尽情读文件
println(reader.readText())
} // ⬅️ 只要代码一离开这个大括号,它就会自动帮你执行 reader.close()!
为什么 use 这么厉害?
inline(内联)函数,在编译时会直接铺开,不会产生额外的函数调用开销。close 也抛了异常,它会聪明地把 close 异常压到业务异常下(Suppressed),不会吃掉真实报错。一句话:需要 close() 的东西,别犹豫,套上 .use {} 就对了!✨
当我们在 Android 项目中使用 Version Catalog (libs.versions.toml) 来集中管理插件和依赖时,有一个非常容易踩的深坑!
⚠️ 核心避坑指南:
所有在子模块中实际 apply(应用)的插件,都必须先在项目根目录的 build.gradle.kts 中声明,并且显式地加上 apply false!
// 根目录的 build.gradle.kts
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
}
🤔 为什么要多此一举?
这是由 Gradle 的运行机制决定的:
在项目构建前,Gradle 需要先解析所有插件的 classpath(也就是搞清楚去哪里下载这些插件的代码)。
如果在根项目中不预先声明并设为 apply false,直接在子模块调用,Gradle 就找不到下载路径。
根项目的这行代码,其实是在告诉 Gradle:“你负责帮我去把这些插件的包下载好,放在那里备用,但先不要在我这个根项目上执行任何操作(下载但不应用)。”
只有当根项目做好了这步准备工作,底下的子模块在声明插件时,才能顺利调用并让插件真正在自己身上生效!这可是现代 Android 工程化管理的基础常识哦!✨