提高Android开发者生产力的最佳实践

@author ASCE1885的 Github 简书 微博 CSDN 知乎
本文由于潜在的商业目的,不开放全文转载许可,谢谢!

lufy.png-548.2kB

本文是翻译自:https://tech.zalando.de/blog/best-practices-for-android-developer-productivity/,欢迎留言讨论!

软件开发中效率的提高不仅取决于开发者的知识深度和专业技能,而且依赖于TA使用的工具,正确的环境配置以及团队协作。我最近在 Droidcon Berlin 2016 上面就我所在的 Zalando 技术团队如何提高 Android 开发者生产力的最佳实践作了一次演讲。下面是此次演讲的一些关键点,希望能让你的开发实践更加愉快,并产出更稳健的应用。

AndroidManifest 的合并

我们都知道在代码编辑器中看到的 AndroidManifest.xml 文件和最终打包进 APK 的 AndroidManifest.xml 文件内容可能不是一样的,例如如果你的工程依赖的第三方函数库在它自己的 AndroidManifest.xml 文件中包含了额外的 <uses-permission/> 标签,那么这些标签将会和你的工程的 AndroidManifest.xml 中的权限配置进行合并。(具体可以参见这个博文:https://commonsware.com/blog/2015/06/25/hey-where-did-these-permissions-come-from.html

为了在编译阶段检查项目中的 Manifest 文件内容,我们可以使用从 Android Studio 2.2 版本开始引入的 Merged Manifest Viewer1。这个工具将会根据构建的 types,flavors 和 variants 来显示工程的 AndroidManifest.xml 是如何和它依赖的函数库中的 AndroidManifest.xml 文件进行合并的。在 Android Studio 中打开工程的 AndroidManifest.xml 文件,如下所示可以看到 Merged Manifest 标签:

image_1b1s0rgseo5f17841aigvvvbmr9.png-160.7kB

运用好 Support annotations

另一个有用的工具是 support annotation 函数库,通过在 Module 的 build.gradle 文件中添加如下依赖即可引入这个函数库:

dependencies {
    compile 'com.android.support:support-annotations:23.4.0'
}

在代码中使用这些元注解有助于发现潜在的 bug 并规范编码规则。最常使用的注解有标记元素可为空,不可为空,指明整型值代表的是资源文件,以及指明在哪个线程中调用等等。

由于这些注解都是元注解,因此即使你的代码违反这些注解的规则依然可以通过编译。当然,在 Android Studio 中会高亮显示这些违反规则的地方,同时在持续集成工具的输出结果中也会给团队中其他人员知晓。

快速无痛的 Code Review

假设你要进行 Code Review,在这之前,你需要先了解 review 的代码是如何工作的,具体实现什么功能,因此你需要对工程进行编译并看到实际的运行效果,通常流程如下:

  • 暂存当前分支你的本地修改
  • 检出需要 review 的代码所在分支
  • 重新加载 Android Studio 中的 gradle 配置
  • 重新加载代码
  • 编译并启动应用,然后进行测试
  • 重复上面的步骤

你可能会问,这样有什么问题吗?当然没有问题,但如果你的项目拥有超过 1000+ 的类以及各种构建配置,在一台配置强大的 Macbook 上面你可能至少也需要花费三分钟的时间才能完成编译。

我们的解决方案是进行 code review 时使用另外一个独立的 IDE 和代码仓库文件夹,而不是和你的开发代码混合在一起。这样的话,你原来的工作就不会受到影响,可以随时回到原来的 IDE 和代码分支继续原来的开发。同时,我们推荐你电脑的配置至少保证有 16GB 的 RAM,这将会节省你很多的时间。

快速的使代码修改生效

即使你的 Android 项目比较小,还是会经常花费时间在等待编译和安装上面。如果工程中类和 xml 布局文件的个数成百上千个,那么每次修改后重新构建和重新安装将会花费你很多的时间,即使使用性能强劲的电脑。而且,重新安装后,你还需要重新点击页面导航进入到你修改后的页面,这也是降低开发效率的过程。

在 2015 年底,Android 社区有了两个工具来实现代码修改的快速部署。其中之一是 JRebel2,它起源于 Java 后端的开发而且早就已经是行业标准了。另外一个工具是 Google 开发团队随着 Android Studio 2.0 发布的 Instant Run[^3]。这两个工具都有着相同的目的,但 JRebel 拥有更多的特性,当然它是需要付费使用的。

我没有找到关于这两个工具的独立比较,因此我根据这两个工具的文档和可找到的博客文章作了下面这个对比的表格。目前,这两个工具最常使用的场景是修改资源和方法的逻辑,而不是修改接口或者 manifests 文件等结构性的修改。

c0d0528550332bba7aa5b23f468d49b2dd0566da_table-android-jrebel.png-38.3kB

参考的资料主要有:

两个工具都处于很活跃的开发阶段,每周都有新的优化和更新。从我们团队的实践来看,很多的使用场景还没有覆盖到,但如果你了解它们提供的能力,你已经可以享受到它们带来的好处了。

测量代码执行的时间

在应用调试和性能分析中一个很有用的特性是使用日志记录方法的输入输出以及执行时间。为了实现这个功能,我们可以使用 Jake Wharton 开发的一个方法注解工具:Hugo[^4]。如果你只是想要看日志那么 Hugo 将是你的第一选择,而不是使用复杂的工具例如 Systrace。

你所需要做的仅仅是在目标方法上面加上一个注解,如下所示:

@DebugLog
public String getName(String first, String last) {/* ... */}

然后在 Logcat 中可以看到如下的日志:

V/Example: --> getName(first="Jake", last="Wharton")
V/Example: <-- getName [16ms] = "Jake Wharton"

如何读取设备的 logcat 日志

在日常开发中,我们大多数人都使用 Android Studio 中的 Android Monitor 来查看日志,对于简单的场景来说够用了,但这个方法存在如下缺陷:

  • 日志很难阅读,你需要使用外部的工具或者配置来进行日志格式化
  • Android Studio 的日志记录工具是和你部署的应用的进程 ID 绑定的,如果你重新部署应用或者杀掉了进程,那么之前的日志将会丢失。

这个问题的解决方案很简单,我们可以使用 Jake Wharton 开发的 pidcat[^5] 工具。它的优势在于:

  • 具备良好的配色方案和格式化
  • 通过应用包名而不是进程 ID 来关联被调试的应用,因此,所有这个应用的日志在重新部署后都不存在丢失的现象

网络输出的日志记录和分析

最常见的阅读应用网络通信日志的方式是使用 HTTP 函数库的日志记录功能,然而,这种方式有如下几个缺陷:

  • 开发过程中如果开启所有网络请求的日志记录,你将会看到应用的性能有所下降,因为它要花费时间来进行 log 的打印
  • 如果你的应用使用的第三方函数库也有日志记录(例如 Google Analytics),你可能需要进行额外的配置使得这些函数库的日志也能够正常输出
  • QA 进行测试时,他们一般是不能看到控制台输出以及一些特殊配置的,在生产版本的应用中你也监控不了网络日志。

另外一种方法是使用 HTTP 监控和代理工具例如 Charles Proxy[^6]。这类工具一般提供如下能力,而且是将你的应用当作黑盒进行处理:

  • HTTP/HTTPS 网络流量的监控和记录
  • 重写网络响应中的取值并进行边界测试
  • 在网络请求中设置断点
  • 在设备中安装 SSL 证书从而读取加密的网络信息

Android 版本兼容性测试

我一直在做而且鼓励同事们也去做的一件事情是对每个开发的特性都在 Lollipop 或者更高的系统,以及 Lollipop 之前的设备和模拟器中去进行测试。这听起来像一个上行下效的决定,但我通过这种测试发现了一些兼容性的 bug。

通过这种方式你能够发现的最多的 bug 是触摸反馈和系统颜色相关的。我们还经常看到由于旧 API 的兼容性问题导致的应用崩溃。

UI 自动化测试

我们通常需要在不同的设备上面进行 UI 界面的点击和输入来检查页面是否存在兼容性问题。如果你有三四台设备要进行测试,并走查多达三十个场景,那这个测试将是令人崩溃的。

自动化测试的第一步是通过输入 adb 命令或者通过完整的脚本来代替手工点击测试。例如,adb 命令行中输入 keyevent 4 将会触发设备上面一个按钮的 UP 事件。通过这种方式可以模拟系统的点击,键盘的输入和屏幕的触摸事件。

那么如果你有多台设备要测试相同的场景呢?我们可以使用 Roman Nurik 开发的 adb-ninja[^7] 脚本来同时提交命令到不同的设备上面。它是一个很小的 shell 脚本,支持同时发送输入的 adb 命令到连接的不同设备上面,从而节省很多时间。

检查你的 build.gradle 配置

即使是资深的开发者有时也会遵循过时的 gralde 配置。让我们来检查一下你的 build.gradle 文件:

  • 使用 jcenter 而不是 mavenCentral 作为依赖的托管仓库,jcenter 有更快的响应速度而且是 mavenCentral 的超集
  • 检查 gradle 的 Android Plugin 版本号,最新的版本能够提高构建的性能,同时包含更多的特性,例如 Instant Run
  • 在指定函数库依赖的版本号时,不要指定一个版本范围,而是要指定明确的版本号,例如 23.4.0,这样在版本升级后如果出现 API 不兼容时不会导致项目编译失败。同时指定明确的版本号,也可以避免在每次构建时都去 jcenter 上面检查是否存在最新的版本。
  • 在开发阶段,使用构建 flavors 来设置 minSdkVersion 为 21 或者更高版本,这有助于实现更快的构建。

上面就是我在 Droidcon Berlin 2016[^8] 上面的分享的一些关键点,完整的演讲 PPT 发表在 Speakerdeck[^9] 上面。

我的新书《Android 高级进阶》开始正式发售了,欢迎选购!

欢迎关注我的微信公众号 ASCE1885,专注与原创或者分享 Android,iOS,ReactNative,Web 前端移动开发领域高质量文章,主要包括业界最新动态,前沿技术趋势,开源函数库与工具等。

猜你喜欢

转载自blog.csdn.net/ace1985/article/details/53230445