Android 开发最佳实践指南:基于 android-best-practices 仓库的 Futurice 工程规范与实战要点
发布时间:2026/10/1 2:36:38 锦皓数字建站

文档教程移动开发【免费下载链接】android-best-practicesDos and Donts for Android development, by Futurice developers项目地址https://gitcode.com/gh_mirrors/an/android-best-practices点击查看免费下载本篇技术指南以本仓库中的 土耳其语翻译版最佳实践文档 为骨架系统梳理 Futurice 团队在 Android 开发中沉淀的工程规范从 Gradle 构建配置、项目结构、第三方库选型到资源文件组织、测试框架、ProGuard 与数据存储覆盖 Android 应用从搭建到发布的完整链路。读者读完可掌握一套可直接落地的 Android 工程实践清单并能依据仓库根目录下的 英文原版 README.md 对照出这些规范随生态演进的脉络为自己的项目做出更贴合现状的技术决策。一、Android SDK放对位置省去重装之苦将 Android SDK 放置在与应用程序无关、方便访问的位置例如用户主目录。部分 IDE 在安装时会自带 SDK并把它放到 IDE 所在的目录之下这并不方便当你需要升级或重装IDE 时可能连 SDK 一起丢失被迫进行漫长而枯燥的重新下载。另外如果你的 IDE 不是以 root 权限运行的还应避免把 SDK 放在需要系统级权限sudo/admin的目录中以免引发权限问题。这一原则在 README.md 中同样被强调——SDK 位置应该独立于 IDE成为开发者自己可控的资源。二、构建系统让 Gradle 成为默认选项构建系统应默认选择Gradle配合 Android Gradle 插件。相比 Ant——功能更受限、需要更多命令——Gradle 具备以下能力构建应用的不同变体build variants编写可读的自定义任务管理与下载依赖组织 keystore 签名配置以及更多功能Android 的 Gradle 插件由 Google 持续开发正逐步成为依赖管理方面最主流的方案。更重要的是应用的构建流程应当由 Gradle 文件定义而非依赖 IDE 专属配置这样才能保证不同工具之间构建结果一致并为持续集成系统提供良好支持这一点在英文版 README.md 中有明确说明。三、项目结构从旧结构迁移到新结构历史上存在两种流行的项目结构旧的 Ant Eclipse ADT 结构与新的 Gradle Android Studio 结构。应选择新结构若还在使用旧结构应视其为历史遗留并尽快迁移。旧结构old-structure ├─ assets ├─ libs ├─ res ├─ src │ └─ com/futurice/project ├─ AndroidManifest.xml ├─ build.gradle ├─ project.properties └─ proguard-rules.pro新结构new-structure ├─ library-foobar ├─ app │ ├─ libs │ ├─ src │ │ ├─ androidTest │ │ │ └─ java │ │ │ └─ com/futurice/project │ │ └─ main │ │ ├─ java │ │ │ └─ com/futurice/project │ │ ├─ res │ │ └─ AndroidManifest.xml │ ├─ build.gradle │ └─ proguard-rules.pro ├─ build.gradle └─ settings.gradle两种结构的核心差异在于新结构明确用 Gradle 区分了不同源集source sets例如main与androidTest。你可以在src下增加paid、free等源集目录让应用按需获得不同特性。保持一个高质量的app文件夹能将应用与其它库项目清晰分离settings.gradle则负责记录app/build.gradle将要引用的库。英文原版 README.md 也指出除非有充分理由否则应接受 Gradle 的默认结构以简化构建脚本。四、Gradle 配置要点4.1 通用结构总体结构请遵循 Google 官方的 Android Gradle 用户指南见 README.md 中推荐的做法。4.2 小任务用 Gradle 而不是外部脚本对于构建过程中的小任务与其编写 shell、Python、Perl 等外部脚本不如直接用 Gradle 实现。可参考 Gradle 官方文档中的任务编写方式英文原版还补充了 Google 提供的 Android 专属 Gradle 食谱详见 README.md。4.3 密码与敏感数据务必放进 gradle.properties在build.gradle中需要为发布版本定义signingConfigs。不要这样写——明文密码会进入版本控制系统signingConfigs { release { storeFile file(myapp.keystore) storePassword password123 keyAlias thekey keyPassword password789 } }正确做法是创建一份不要提交到 VCS的gradle.properties文件KEYSTORE_PASSWORDpassword123 KEY_PASSWORDpassword789Gradle 会自动导入该文件因此在build.gradle中可以直接引用并用try/catch兜底提示signingConfigs { release { try { storeFile file(myapp.keystore) storePassword KEYSTORE_PASSWORD keyAlias thekey keyPassword KEY_PASSWORD } catch (ex) { throw new InvalidUserDataException(You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.) } } }4.4 优先用 Maven 依赖解析而不是直接导入 jar直接往项目里塞 jar 文件会使依赖冻结在某个特定版本如2.1.1下载更新与版本更换都很繁琐——这正是 Maven 已解决的问题。应尽量使用 Maven 坐标声明依赖例如dependencies { implementation com.squareup.okhttp:okhttp:2.2.0 implementation com.squareup.okhttp:okhttp-urlconnection:2.2.0 }4.5 避免动态依赖版本号避免使用2.1.这类动态版本号不同构建之间可能引入未察觉的行为差异产生难以排查的隐性 bug。使用2.1.1这样的静态版本才能得到稳定、可预测、可复现的构建环境英文原版 README.md 表述与此一致。4.6 非发布构建使用独立的包名后缀利用applicationIdSuffix为debug构建类型添加后缀使 debug 与 release 两个 APK 能同时安装在同一台设备上——应用发布后这一点尤其重要android { buildTypes { debug { applicationIdSuffix .debug versionNameSuffix -DEBUG } release { // ... } } }同时建议为不同构建类型配置不同图标方便在设备上区分。Gradle 使这变得非常简单在默认项目结构下将debug图标放入app/src/debug/resrelease图标放入app/src/release/res也可以通过versionName或按构建类型修改应用名称来实现。五、IDE 与文本编辑器你可以使用任何能正确遵循项目结构的文本编辑器编辑器选择纯属个人偏好但务必营造一个能遵循项目结构的工作环境。当前最受推荐的 IDE 是Android Studio理由包括由 Google 开发维护、原生支持 Gradle、内置新项目结构模板、专为 Android 开发打造、且已趋于稳定。而Eclipse ADT已不再被推荐使用Google 已于 2015 年底停止 ADT 支持并建议用户迁移到 Android Studio。若仍继续使用 Eclipse由于它基于旧项目结构与 Ant你需要额外配置或从命令行运行 Gradle。同样可以使用 Vim、Sublime Text、Emacs 等文本编辑器但此时需要习惯在命令行中运行 Gradle 与 adb。无论选择何种编辑器都要确保 Gradle 与项目结构符合规范且不要将编辑器专属文件提交到 VCS例如 Ant 的build.xml。务必保持build.gradle最新且可运行时刻替其他开发者着想——他们不应被迫为你收拾项目环境。英文原版 README.md 还补充应避免将 Android Studio 的.iml等本地配置提交到版本控制它们往往包含你本机的专属配置对同事无效。六、第三方库选型6.1 JSON 解析JacksonJackson是一个 Java 的 JSON 序列化/反序列化库。同类中最常用的还有Gson但 Jackson 之所以被优先推荐是因为它提供多种 JSON 处理方式流式解析streaming、内存树模型in-memory tree model以及经典的 JSON-POJO 数据绑定data binding。需要留意的是Jackson 体积比 Gson 更大在 65k 方法数限制下可能需要对库做取舍调整。其他可选方案还有 Json-smart、Boon JSON。英文原版 README.md 则指出Gson 体积更小若想规避 65k 方法限制可以优先考虑Square 的 Moshi 则吸收了 Gson 的开发经验并与 Kotlin 集成良好。6.2 网络、缓存与图片不要重复造 HTTP 客户端向后端服务器发起请求已有大量久经实战检验的客户端方案不应再自己实现 HTTP 客户端。土耳其语版本推荐的是Volley或RetrofitVolley同时提供图片加载与缓存能力Retrofit选择它时可搭配Picasso做图片加载、OkHttp做高效的 HTTP 请求。三者同属一家公司Square相互配合良好OkHttp 也可以与 Volley 结合使用。英文原版 README.md 的建议在此基础上演化为以OkHttp为基础提供高效 HTTP 请求用Retrofit提供类型安全层图片加载缓存考虑PicassoGlide是另一个图片加载选项支持 GIF 动图、圆形图片但方法数也更大。6.3 响应式编程RxJavaRxJava是用于响应式编程Reactive Programming的库本质是处理异步事件。这是一个强大但也陡峭的范式在用它重构整个应用架构之前应审慎评估。土耳其语版本还给出了循序渐进的学习路径没有 Rx 经验时先仅将其应用于后端 API 响应的处理或者先用于简单的 UI 事件处理如点击事件、搜索框输入监听当确信技能足够、想将其推广到整个架构时务必为所有棘手之处编写 Javadoc——因为未来接手项目的同事可能对 Rx 一无所知代码应尽可能易读。英文原版 README.md 进一步建议配合RxAndroidAndroid 线程支持与RxBinding将 Android 组件转化为 Observable并以 Futurice 的开源应用 Freesound Android 作为大量使用 RxJava 2 的参考案例。6.4 Lambda 语法RetrolambdaRetrolambda允许在 Android 及 JDK-8 之前的平台上使用 Lambda 表达式语法使代码更紧凑清晰尤其在配合 RxJava 的函数式写法时获益明显。配置步骤如下安装 JDK 8设置JAVA8_HOME与JAVA7_HOME系统变量在build.gradle的根构建脚本中添加dependencies { classpath me.tatarka:gradle-retrolambda:2.4.1 }在每一个 Gradle 模块中应用插件并配置apply plugin: retrolambda android { compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } retrolambda { jdk System.getenv(JAVA8_HOME) oldJdk System.getenv(JAVA7_HOME) javaVersion JavaVersion.VERSION_1_7 }Android Studio 本身也为 Java 8 Lambda 提供代码辅助。若你是 Lambda 新手记住两点即可只含一个方法的接口是lambda 友好的可以折叠成更紧凑的语法拿不准参数写法时先写匿名内部类再让 Android Studio 帮你自动折叠成 Lambda。需要说明英文原版 README.md 指出从 Android Studio 3.0 起已不再需要 Retrolambda。6.5 警惕 65k 方法数限制克制使用库尤其避开 GuavaAndroid 应用打包为 dex 文件后可被引用的方法数存在65536 的硬上限一旦超过编译将直接报致命错误。因此应尽量使用少量的库用 dex-method-counts 这类工具计算哪些库组合能保持在限制之下尤其避免 Guava——它内部包含超过 13k 个方法。七、Activity 与 Fragment 的取舍社区乃至 Futurice 内部对如何用 Activity 与 Fragment 组织最佳架构并无共识。Square 甚至推出了 Mortar 这类主要基于 View 构建架构的库来绕开 Fragment但这在社区中仍未被广泛认可。从 Android API 的发展历史看可以粗略地把Fragment 视为屏幕的 UI 片段通常与 UI 相关把Activity 视为控制器对生命周期与状态管理尤为重要。不过角色也存在变化Activity 可能承担 UI 角色如屏幕切换过渡Fragment 也可能被单独用作控制器。每种方案纯 Fragment 架构、纯 Activity 架构、纯 View 架构都有各自的缺点应审慎决策。以下几点值得注意也请结合自身场景判断避免过度使用嵌套 Fragment易触发套娃 bugmatryoshka bugs。仅在确实合理的场景使用例如屏幕型 Fragment 内、水平滑动的 ViewPager 中的子 Fragment避免在 Activity 中堆积大量代码尽可能让 Activity 保持轻量主要承担生命周期与 Android 交互 API 的职责。优先使用单 Fragment 的 Activity把 UI 代码放进 Fragment——这为将来改为 Tab 布局或多 Fragment 平板界面留出复用空间。每个 Activity 尽量对应一个 Fragment除非你已深思熟虑。另外要谨慎对待操作系统层面的操作最大的坑往往出现在 Intent 使用上这些 Intent 会影响 Android 操作系统或其他应用可能引发 bug。例如若应用通过 Intent 进行跨包通信设备开机后可能出现数秒延迟。八、Java 包结构遵循 MVC 思想组织代码Java 层的 Android 架构大体可用Model-View-ControllerMVC来描述在 Android 中Fragment 与 Activity 承担控制器角色同时也是 UI 的一部分。正因如此把 Fragment 或 Activity 直接放进 view 或 controller 包里是不妥的放入fragments包更合理。若遵循前述Activity 尽量保持轻量的指引将 Activity 放在顶层也无妨若需要 2、3 个及以上 Activity可放入activities包。其余部分则是典型的 MVC 形态models存放从 API 响应 JSON 反序列化得到的 POJOviews存放自定义 View通知、ActionBar 视图、widget 等由于 Adapter 是数据与视图之间的中介、且常通过getView()获取视图adapters可作views的子包managers存放覆盖整个应用、贴近 Android 系统层的控制器类utils存放各类数据处理类如DateUtilsnetwork存放与后端通信的类。从最接近后端到最接近用户整体结构如下com.futurice.project ├─ network ├─ models ├─ managers ├─ utils ├─ fragments └─ views ├─ adapters ├─ actionbar ├─ widgets └─ notifications值得一提的是英文原版 README.md 已将该建议演进为基于特性feature-based的包结构其收益包括更清晰的特性依赖与接口边界、促进封装、更易理解组成特性的组件、降低误改无关共享代码的风险、导航更简单、更易移除特性以及更易过渡到模块化构建更好的构建时间与 Instant Apps 支持。九、资源文件管理9.1 命名规范遵循type_foo_bar.xml的前缀约定例如fragment_contact_details.xml、view_primary_button.xml、activity_main.xml。9.2 Layout XML 的组织方式如果不确定如何编排 layout XML可遵循以下约定每行一个属性缩进 4 个空格android:id永远放在第一个android:layout_****类属性放在前面style属性放在最后标签闭合符/单独占一行便于后续添加或调整属性与其硬编码android:text不如使用 Android Studio 支持的 Design-time 属性tools 命名空间。示例?xml version1.0 encodingutf-8? LinearLayout xmlns:androidhttp://schemas.android.com/apk/res/android xmlns:toolshttp://schemas.android.com/tools android:layout_widthmatch_parent android:layout_heightmatch_parent android:orientationvertical TextView android:idid/name android:layout_widthmatch_parent android:layout_heightwrap_content android:layout_alignParentRighttrue android:textstring/name stylestyle/FancyText / include layoutlayout/reusable_part / /LinearLayout核心原则android:layout_****位置、大小、边距等类属性应定义在 layout XML 中其余android:****外观属性颜色、内边距、字体等应放进 style XML。该原则存在例外android:id显然应在 layout 文件中LinearLayout的android:orientation放在 layout 文件中通常更合理android:text定义内容应放在 layout 文件中有时可为一个通用 style 定义android:layout_width与android:layout_height但默认情况下它们应出现在 layout 文件中。9.3 使用 Style避免重复属性几乎每个项目都应当恰当地使用 style——同一个 view 的外观被反复复用的情形非常普遍。例如为正文文本定义一个通用 stylestyle nameContentText item nameandroid:textSizedimen/font_normal/item item nameandroid:textColorcolor/basic_black/item /style应用到 TextViewTextView android:layout_widthwrap_content android:layout_heightwrap_content android:textstring/price stylestyle/ContentText /按钮类同此理。但这只是起点——把一组相关且重复出现的android:****属性整体迁移到公共 style收益更大。9.4 拆分大型 style 文件你不需要只有一个styles.xml。Android SDK 原生支持其他文件名——styles这个名字本身没有魔法真正起作用的是文件内的style标签。因此完全可以拆分出styles.xml、styles_home.xml、styles_item_details.xml、styles_forms.xml等多个文件。与res目录名构建系统能识别其含义不同res/values下的文件名可以是任意的。9.5 colors.xml只做调色板colors.xml里只应存在颜色名 → RGBA 值的映射不要用button_foreground、comment_background_active这类按用途命名的颜色。否则同一 RGBA 值会在多处重复一次简单的颜色调整就要改动许多文件而且这些用途说明本应属于 style不该出现在colors.xml。不要这样写resources color namebutton_foreground#FFFFFF/color color namebutton_background#2A91BD/color color namecomment_background_inactive#5F5F5F/color color namecomment_background_active#939393/color color namecomment_foreground#FFFFFF/color color namecomment_foreground_important#FF9D2F/color ... color namecomment_shadow#323232/color应该这样写resources !-- grayscale -- color namewhite #FFFFFF/color color namegray_light#DBDBDB/color color namegray #939393/color color namegray_dark #5F5F5F/color color nameblack #323232/color !-- basic colors -- color namegreen#27D34D/color color nameblue#2A91BD/color color nameorange#FF9D2F/color color namered#FF432F/color /resources这份调色板可以向应用的设计师索取。颜色名不必是白色蓝色等字面颜色名brand_primary、brand_secondary、brand_negative这类语义化命名同样完全可以接受。以这种方式组织颜色改动更简单也能对用色数量保持掌控——对美观的 UI 而言控制颜色变体数量很重要。英文原版 README.md 还补充了更彻底的三层分离模型colors.xml只定义调色板styles.xml引用调色板并反映颜色用途如按钮前景为白色activity_main.xml引用 style 为按钮着色。必要时还可以再加一层用途颜色资源文件例如color namebutton_foregroundcolor/white/color再由 style 引用之——这种方式利于颜色重构与样式稳定性代价是需维护另一套颜色映射。9.6 dimens.xml像 colors.xml 一样组织出于与颜色相同的目的也应该为字体大小与边距间距定义一个调色板。一个良好的 dimens 文件示例resources !-- font sizes -- dimen namefont_larger22sp/dimen dimen namefont_large18sp/dimen dimen namefont_normal15sp/dimen dimen namefont_small12sp/dimen !-- typical spacing between two views -- dimen namespacing_huge40dp/dimen dimen namespacing_large24dp/dimen dimen namespacing_normal14dp/dimen dimen namespacing_small10dp/dimen dimen namespacing_tiny4dp/dimen !-- typical sizes of views -- dimen namebutton_height_tall60dp/dimen dimen namebutton_height_normal40dp/dimen dimen namebutton_height_short32dp/dimen /resources在布局中margin 与 padding 应使用spacing_****这类通用常量而不是硬编码数值——就像对待普通字符串一样。这能带来统一的外观体验也让样式与布局更易组织与修改。9.7 strings.xml 的命名字符串的 key 应像命名空间一样组织不要害怕让两个或多个 key 复用同一个值——语言是复杂的命名空间能为字符串补充上下文、消除歧义。糟糕的命名string namenetwork_errorNetwork error/string string namecall_failedCall failed/string string namemap_failedMap loading failed/string良好的命名string nameerror.message.networkNetwork error/string string nameerror.message.callCall failed/string string nameerror.message.mapMap loading failed/string此外不要把字符串值全部写成大写遵循正常文本惯例例如首字母大写。若界面需要全大写展示请使用 TextView 的textAllCaps属性糟糕string nameerror.message.callCALL FAILED/string良好string nameerror.message.callCall failed/string9.8 避免过深的 View 层级有时为了完成某个布局效果你会忍不住再嵌套一层 LinearLayout结果可能演变成下面这样的结构LinearLayout android:layout_widthmatch_parent android:layout_heightmatch_parent android:orientationvertical RelativeLayout ... LinearLayout ... LinearLayout ... LinearLayout ... /LinearLayout /LinearLayout /LinearLayout /RelativeLayout /LinearLayout即使 layout 文件中看不到这种显式嵌套也可能在 Java 代码中动态 inflate 视图时发生。其后果包括处理复杂 UI 树带来的性能问题以及更严重的StackOverflowError风险。因此应尽量保持视图层级扁平学习使用RelativeLayout英文原版 README.md 已更新为推荐 ConstraintLayout、掌握布局优化技巧并研究merge标签的用法。9.9 WebView警惕客户端处理与内存泄漏当必须展示网页例如新闻文章页时应避免在客户端侧做 HTML 清理处理而是要求后端程序员提供纯净的 HTML。WebView 若持有 Activity 引用而非绑定 ApplicationContext会产生内存泄漏。另外简单的按钮和表单不必用网页实现优先使用原生控件。十、测试框架Android SDK 自带的测试框架尤其是 UI 测试方面当时仍处于起步阶段。Android Gradle 通过connectedAndroidTest提供设备测试支持基于 Android 的 JUnit 扩展与辅助类运行因此需要在真实设备或模拟器上执行测试。10.1 单元测试Robolectric土耳其语版本推荐使用Robolectric进行单元测试——它能在脱离设备的情况下运行单元与 UI 测试。但要注意在 Robolectric 上做 UI 测试并不准确因为无法观察元素间的动画等行为测试价值有限。需要对照的是英文原版 README.md 已明确不推荐 RobolectricAndroid 构建系统对 JUnit 的支持改善后Robolectric 通过提供 Android 平台的 mock 实现来脱离设备测试无法保证正确性更好的组合是JVM 上的纯 JUnit 单元测试 设备上的集成测试。10.2 UI 测试RobotiumRobotium让 UI 测试编写变得简单。虽然可以写互相独立的 UI 测试但编写有依赖关系、串联操作的测试更能验证应用流程。示例代码极其直观solo.sendKey(Solo.MENU); solo.clickOnText(More); // searches for the first occurrence of More and clicks on it solo.clickOnText(Preferences); solo.clickOnText(Edit File Extensions); Assert.assertTrue(solo.searchText(rtf));对照英文原版 README.md如今的推荐已更新为Espresso编写 UI 测试、AssertJ-Android让断言更简洁例如// Example assertion using AssertJ-Android assertThat(layout).isVisible() .isVertical() .hasChildCount(5);十一、模拟器若以 Android 开发为职业土耳其语版本建议获取Genymotion模拟器的许可证其帧率frame/sec比 AVD 模拟器更快内置网络质量测试、GPS 定位模拟等工具适合批量测试场景可在一台机器上覆盖多设备、多 Android 版本比购置多台实体机划算得多。两点警告Genymotion 不包含 Play Store 与 Maps 等 Play 服务且若要测试三星专属 API仍建议使用真机。对照英文原版 README.md官方模拟器尤其 x86 变体近年性能已显著提升足以应对大多数日常开发场景但真机验证仍不可忽视——重点应放在市场份额大、与你的应用最相关的设备上。十二、ProGuard 配置ProGuard通常用于 Android 项目的代码压缩shrink与混淆obfuscate。是否启用取决于项目配置通常会在发布 APK 时让 Gradle 启用 ProGuardbuildTypes { debug { minifyEnabled false } release { signingConfig signingConfigs.release minifyEnabled true proguardFiles getDefaultProguardFile(proguard-android.txt), proguard-rules.pro } }为确定哪些代码需要保留、哪些可以丢弃或混淆你必须为代码指定一个或多个入口点——通常是含 main 方法的类、applet、midlet、Activity 等。Android 框架的默认 ProGuard 配置位于SDK_HOME/tools/proguard/proguard-android.txt使用上述配置时项目专属规则my-project/app/proguard-rules.pro会被追加到默认配置之后。12.1 常见错误与排查assembleRelease等构建命令成功运行但应用启动即崩溃、抛出ClassNotFoundException或NoSuchFieldException之类的错误是 ProGuard 最典型的坑。它通常意味着两种可能ProGuard 认为某类/枚举/方法/字段/注解不再需要将其删除ProGuard 混淆重命名了类/枚举/字段名但代码某处仍通过原名间接引用如 Java 反射。排查方法查看app/build/outputs/proguard/release/usage.txt确认目标对象是否被移除查看app/build/outputs/proguard/release/mapping.txt确认目标对象是否被混淆。12.2 keep 与 keepnames阻止 ProGuard剥离必需类或成员在配置中加入keep-keep class com.futurice.project.MyClass { *; }阻止 ProGuard混淆类或成员加入keepnames-keepnames class com.futurice.project.MyClass { *; }更多示例见 ProGuard 官方手册。12.3 尽早、反复地做 release 构建在项目早期阶段就应生成并测试发布 APK以确认 ProGuard 规则是否正确保留了依赖。每当引入新库或更新依赖时同样构建一个发布 APK 并在设备上实测。不要等到应用临近 1.0 才首次构建 release——那时你可能面对一堆意外 bug却几乎没有修复时间。提示为每个发布给用户的版本保留mapping.txt。这样当用户上报 bug、提交混淆后的堆栈时你能更快定位问题。12.4 DexGuard若需要更强大的发布代码优化与混淆工具可研究DexGuard——由打造 ProGuard 的同一团队推出的商业产品它还能轻松拆分 dex 文件从而解决 65k 方法数限制问题。十三、数据存储13.1 SharedPreferences简单持久化的默认选择如果应用运行在单一进程、且无需持久化复杂数据SharedPreferences 就是合理的默认选项。以下情况则不适用性能数据复杂或数据量很大多进程访问多个进程需要访问并同步数据例如拥有独立进程的 widget 或远程服务关系型数据数据各部分存在关系且需要强制维护这些关系。英文原版 README.md 补充也可将复杂对象序列化为 JSON 再存储、读取时反序列化但要权衡这种方式的性能与可维护性。13.2 ContentProviders平台标准方案当 SharedPreferences 不够用时应使用平台标准的ContentProviders——更快且进程安全。其唯一缺点是搭建所需的样板代码较多加上劣质教程的误导。不过可以借助Schematic之类的库自动生成 ContentProvider显著减少工作量。仍需要自行编写从 SQLite 列读取数据对象及反向的解析代码。另一种思路是用 Gson 等库将数据对象序列化后只持久化字符串——性能有所损失但不必为数据类的每个字段声明一列。13.3 ORM除非确有需要否则不推荐通常不推荐使用 ORM对象关系映射库除非数据异常复杂且有迫切需求——ORM 往往复杂且学习成本高。若决定使用 ORM务必确认其是否process safe进程安全因为许多现有 ORM 方案恰恰不安全。十四、使用 Stetho 调试Stetho是 Facebook 开发的 Android 调试桥debug bridge与 Chrome 桌面浏览器的开发者工具集成。借助它可轻松检查应用状态尤其是网络流量还能查看与编辑应用内的 SharedPreferences 与 SQLite 数据库。务必确保 Stetho只在 debug 构建中启用绝不要出现在 release 变体中。英文原版 README.md 还补充了备选方案Chuck功能更简化但日志直接显示在设备上对测试人员更友好无需 Chrome 连接配置。十五、与仓库现状的演进对照本文主体依据仓库中的 土耳其语翻译版 整理它忠实记录了 Futurice 团队在某一时期对应 Android Studio 初代、65k 方法限制盛行、Robolectric/Robotium/Genymotion 当道的年代的实践总结。若对照仓库根目录的 英文原版 README.md可清晰看到以下演进脉络供读者决策时参考主题土耳其语版本文主体英文原版 README.md构建Gradle 自定义结构强调 Gradle 默认结构、建议minSdkVersion: 21API 21 起不再需要 multidex 支持库网络Volley / OkHttpOkHttp Retrofit Picasso/GlideJSONJackson优先Jackson 可选Gson 更小、Moshi 集成 KotlinLambdaRetrolambdaAndroid Studio 3.0 起不再需要包结构MVC 分层network/models/managers/utils/fragments/views基于特性的包结构feature-based布局优化RelativeLayoutConstraintLayout测试Robolectric RobotiumJUnit Espresso AssertJ-Android模拟器Genymotion官方模拟器已够用辅以真机调试StethoStetho Chuck新增主题——LeakCanary 内存泄漏检测、持续集成CI、共享 debug keystore、共享代码风格配置这些差异并非矛盾而是 Android 生态在数年间演进的真实写照多 dex65k 限制的缓解、Kotlin 普及、官方模拟器性能提升都让早期的一些规避性建议变得不再必要。读者在落地本指南时建议以英文原版 README.md 为最新基线以本文为历史脉络与原理说明两者结合做出判断。十六、致谢与许可本指南内容源自 Futurice 开发者们的知识分享Antti Lammi、Joni Karppinen、Peter Tackage、Timo Tuominen、Vera Izrailit、Vihtori Mäntylä、Mark Voit、Andre Medeiros、Paul Houghton 等仓库文档与 LICENSE 表明其采用Creative Commons Attribution 4.0 International (CC BY 4.0)许可发布。仓库为只读镜像本文仅介绍查阅与学习方式直接阅读 README.md 及各语言翻译如 中文版、土耳其语版即可获得完整实践清单。赞分享文档教程移动开发【免费下载链接】android-best-practicesDos and Donts for Android development, by Futurice developers项目地址https://gitcode.com/gh_mirrors/an/android-best-practices点击查看免费下载相关推荐android-best-practices安卓开发最佳实践指南android best practices安卓开发最佳实践指南 在安卓开发的世界中遵循最佳实践能够帮助开发者避免重复造轮子提高开发效率。android文档教程移动开发CANN Runtime 错误码 EE1018 深度解析Invalid Argument API Call SequenceAPI 调用序列非法CANN Runtime 错误码 EE1018 深度解析Invalid Argument API Call SequenceAPI 调用序列非法 EE10文档教程移动开发Android 开发最佳实践实战指南以 android-best-practices 为核心的构建、架构与工程质量全链路准则Android 开发最佳实践实战指南以 android best practices 为核心的构建、架构与工程质量全链路准则 本文以开源仓库 android文档教程移动开发上一篇OGX Responses API 完全指南生产可用的 OpenAI 兼容服务端 Agent 编排下一篇3分钟解锁网易云音乐免费NCM转MP3终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。