首页 > 编程语言 > Java Web开发 > 安卓开发常用工具和第三方库汇总
2017
09-29

安卓开发常用工具和第三方库汇总

我的名字叫 Ryan Cooke 我在 Pinterest 的核心体验团队工作。今天在这里我会谈论各种 Android 库:它们各自的优点,缺点和其他相关知识。目的是高效地概述尽可能多的库,这样,当你遇到一个问题的时候,你知道这是不是个已经解决的问题?什么样的方案更好?同时也能帮助你避免那些陷阱。

选择正确的库意味着你可以拥有一个已经成熟的更好的解决方案,而不是花费三个月来重新构建它。了解这些库是第一步。

我听到很多人想要实现第一个库, 我们难道不能用 Async 任务或原生的东西来做吗? Google 觉得,如果市面上已经有一个解决方案了,他们就不想建立一个一模一样的竞品。他们在多个地方多次表达过这个想法。但是你应该知道,你还有一些别的选择。

一般提示

库最有价值的地方在于 可逆 :你将库添加到你的应用程序中,之后也可以将其删除(没有任何开销)。随时都能拿出来。不是所有的东西都可以这样,但如果它可以的话,请把它做成一个库,而不是和你的应用终生绑在一起。

一个更好的方法是在把你的库封装起来。如果你自己的类调用了库的方法,那么这样做就有着许多的好处,可以让使用者调用你自己的 API。例如,在某些情况下如果库返回异常,你想在 API 里截获它。你只用修改一个文件。有一个封装器让你的库更易用些。

如果你正在做一个库,你的团队里面的某些人可能已经开始使用它了,他们知道该如何调用你的库,而不用你的封装。这个检查样式会在编译的时候抛出异常,或者在应用中当他们为连接类使用 import 语句时,提示他们“不要使用连接类,使用封装的 API”。你还会指出不要在这个特定文件上这样做。如果你不这样做,封装器用处就不大,因为人们最终会绕过它。

另外, 对第三方库做单元测试 也是一个好主意。你需要这些测试,如果你正在使用 Joda-Time 这样的库,你可以使用单元测试来了解它奇怪的边界情况。你甚至可以通过单元测试来了解它的工作原理。你可能会发现,如果你不用 add day 方法而是给今天加一的话,你可能会出现二月三十日的情况。

在 Android 的世界中,我们必须考虑 函数数量限制(64,000) 。( 我在说第三方函数库的函数数量,它们会被精简掉 )。有一个网站[函数数量](http://methodscount.com),你可以上传你的库,Gradle 导入语句,然后它会告诉你这个库有多少个方法(这是件很棒的事情,特别是当你想使用该库的时候)。使用 ProGuard,许多库将会变得很小。这个方法使你只会包含库中被引用的部分,但是在使用库之前是很难预测你将要使用的内容的。有些时候你可以这样做,“我知道我只使用库的这个方法”,看看它有多小。

Dex函数计数 会在你的 gradle 里,你也可以在你自己的编译系统上这么做,跟踪你应用程序中函数的总个数。 Apk-method-count 是一个很棒的工具。你可以拖动你的 APK,看看它有多少个方法(63,905 个方法,我喜欢生活在 64,000 的边缘)。在 MultiDex 限制出现之前,你添加的每个方法仍将减慢那些旧设备的启动时间。虽然你的船已经航行,不受 MultiDexing 的限制,十万种方法和十二万种方法之间还是有差别的。更少的方法总是有好处的。 Instagram 就是以 从库 中提取所需的东西而不是使用完整的库而闻名的。这是一个很好的实践,如果你有精力这样做的话。

除此之外,我还建议关注 流行的成熟库 。每个月(特别是如果你订阅了 Reddit Android 开发者),你将会听到最新,最酷的库。库越成熟,就会越受欢迎。与现有的项目一起工作,兼容性问题就越少。无论何时遇到问题,stackoverflow 那里都会有答案。

另外,请注意特殊的方法。这是不符合 Java 标准的东西。如果你正在构建完全不同的布局,那么很可能会有兼容性问题。这时采用库就会变得更加犹豫。

社交登录

Facebook 是社交登录的黄金标准( 如果你不喜欢 Facebook 的实现,情况只会变得更糟 )。他们提供测试用户,你可以使用这些测试账户来测试。不再需要假帐户了,你应该使用他们的测试帐户 - 它们工作的更好。我看过有人犯过这样的错误,你不能假设每个 Facebook 用户都有电子邮件。大约 10 到 15% 的 Facebook 用户没有电子邮件。如果你期待电子邮件,这可能是 10 到 15% 的注册失败的神秘原因。他们需要密钥散列( 这是一个随机序列,某段代码打印出的键值哈希 ),所以你不必处理它,不用理会它。如果你想申请些其他的疯狂权限,他们现在已经锁定了这些权限。他们需要先看看你打算如何使用这些权限,如果你有这个疯狂的想法而且应用还没有开发好,请提前告知他们。

登录和注册时,请记录你所得到的错误。这是我们如何发现由于没有电子邮件,10 到 15% 的注册失败的方法。有时候记录错误可能是找到你不了解的东西的最有效的方法。

还有很多其他登录选项:Twitter,LinkedIn,Google。我的心态是(特别是 Twitter,LinkedIn),虽然他们很受欢迎,但往往不值得的尝试。你会看到不到 2% 的注册率,除非是一个非常好的场景。 LinkedIn 提供了非常具有挑战性的 API( 这不是我原来的单词,但是 PR 告诉我,我应该改变它 )。 Twitter,他们不提供很多信息,但你可以 转到此链接 , 并且说我需要电子邮件和基本信息,他们会给大家授予权限。但总体来说,除非你的架构非常好,这些都会增加你应用的复杂性,。

Google 情况比较复杂。在 Android 上,很多人都会拥有 Google 帐户。如果他们没有 Google 帐户,是非常奇怪的。但是你可以从 Google 登录中获得很多功能 - 你可以获取电子邮件提示和其他东西。此外,登录 UI 是十分丑陋的。还有点慢,所以你必须考虑加载模式的对话框。

联网

如果你使用本地库,那么有两个大名鼎鼎的库:Retrofit,Volley。还有 native HTML URL Connect(通常不推荐)。对于 Retrofit 和 Volley 来说,你经常会看到些比较,你会看到 Volley 比 Retrofit 做的更多(例如图像下载和 neat )。这具有欺骗性。

Retrofit 是由 Square 建造的,他们有一个哲学,他们的库会尽可能少做事情。他们试图让库严格地解决具体的问题,解决这个问题时,强制执行良好的实践。Retrofit 可能是他们最好的例子。这段代码( 见幻灯片 )是我在一个应用程序中使用 Retrofit 的示例,我必须为我的 API 调用创建一个非常干净的接口。

Get more development news like this

Volley 给你足够的绳子吊死自己。你可以使用 Volley,很容易用错。Retrofit 更好地强化了最佳实践,我喜欢这样的做法。

很多时候你会听到 OkHttp:这是真正的幕后大举提升网络性能的功臣。它已经在 Android 4.4 的 native 里面了。

网络调试

考虑到网络调试,你有网络调用正在进行,你想了解发生了些什么。

Stetho

Stetho 是一个很好的选择。它是 Facebook 开发的。它为你的网络调用提供了 Chrome 开发者工具视图。它还提供了许多其他的好东西:可以查看你的数据库,看看那里发生了什么;可以看到你的布局,如果你不知道屏幕上发生了什么。其中需要注意的是,你必须在每次运行时启动它,否则它会自动关闭。虽然时间是准确的,但它会使你网络调用的时间更长。

HttpLoggingInterceptor

我个人倾向于另一个简单的 HttpLoggingInterceptor。你将拦截器添加到你的网络请求中,并将其打印在日志文件上。你也可以看到一些 JSON 文件。有一堆类似的东西都命名为 logging 拦截器。使用 Square 的标准 HTTP 日志记录可以让你更轻松地浏览,非常方便。

图片

作为在 Pinterest 工作的人,图片很重要。如果你正在做图片相关的应用,你可能希望使用第三方库来处理图片缓存,图片下载和图片大小调整。

Picasso,Glide

图片处理库里最有名的两个库是 Picasso 和 Glide。他们有着非常相似的接口;对于大多数标准用户来说接口基本相同。

Picasso 较小。最新版本从 2,879 行缩小到 849 行。但是,Glide 倾向于提供你想要的每个功能:它可以加载 GIF,也可以显示视频预览图像。

如果你正在加载图片,Picasso 比较合适。它更受欢迎:它有更多的文档,更多的支持。两个库都很好。如果你一直都有些奇怪的场景,你可以冒险使用 Glide。如果你的使用场景很标准,Picasso 是一个不错的选择。

提示

我已经提到我在 Pinterest 工作,而且图像对我的工作很重要。我必须扔出一堆关于图像的提示。

人们都没有做最简单的事情,因为这些库没有这样做,这件简单的事情就是在列表中预取。每当你滚动列表时,你都会看到图像在加载。如果你预取了下一个或两个图像,那么当你滚动时,将会减少帧丢失。这会给你带来更好的体验,不需要等待加载了。如果你预取的图像太多,资源就会竞争,也不好,但预取下一个或两个图像一定会带来更好的体验。

除此之外,这些库都不能解决你图像的内存问题。最简单的做法是禁用图像,然后计算出应用程序中的图像消耗了多少内存。不使用图像,计算出省下的内存消耗。另外,释放没有显示图像的图像,并将图像的大小调整为你显示的尺寸也可以帮助节省内存。 Cloudinary 是一个很酷的托管服务,你可以以特定的分辨率请求图像。他们努力做到这点。但是,当你调整请求的图像大小时,你必须确保你没有通过请求类似的图像来破坏缓存(所以这里有个平衡)。

我是 bigHeap 的粉丝。我们的一个的应用程序,使用了 bigHeap 后,内存崩溃降到原来的 1/4。 Google 不鼓励使用它,因为它关闭了在后台的其他应用程序,因此应用程序之间的切换并不是那么好。但在某些时候,这不是你的问题。垃圾回收也需要更长时间,你可以使用它来屏蔽内存问题(你不应该这么做)。一般来说,bigHeap 是好的。如果你去 Play Store,并且搜索 largeHeap,你可以下载一个很酷的应用程序,它会显示你手机上启用了 bigHeap 的应用程序。你会注意到现在几乎每个人都陷入了困境,并且正在使用 bigHeap。

当你想到内存和图像时,这里有一个简单的公式。有些人会问,“这是个两千字节的 JPEG,为什么我的实际使用的内存会这么大呢?” 使用的内存是像素宽度乘以像素高度的四倍。这就是你期望的大小。它们的标准格式是 ARGB_8888 - 它用四个字节存储颜色空间。如果你使用 RGB_565,你可以将其减少到两倍。但是颜色彼此会非常相似,你会看到更少的色彩空间,它也不能做 alpha,但它会减少一半的内存使用量。你可以考虑在低端设备或低版本 API 上进行此操作。这是节省内存不足问题的好方法。

Fresco

Facebook 发布了一个神奇的库,解决了 API 21 之前的所有版本的内存不足问题。在 API 21 之前,Android 系统中出现了一个错误,你可以在应用程序内存之外使用其他的内存。但是会带来些奇怪的情况:你的程序在旧设备上没有问题,但在新设备上会表现更糟。因为它加载的方式与其他库非常不同,所以它可以实现渐进式 JPEG 这样的图像,图像在图层中逐渐加载。但是,它们会更深入地耦合在你的应用程序中。借助 Glide 和 Picasso,你可以将其与你的应用隔离的很好。而不使用 imageViews,你必须使用它们的类型 Drawees,并且还会产生更多的孤岛代码。

如果你定位较低端的设备,你在旧设备上有更多的内存需求,我建议你使用 Fresco。除此之外,我会坚持 Picasso 和 Glide。

内存 - 泄漏

LeakCanary

LeakCanary 是当今内存泄露的神器,它可以帮助你找到内存泄露的地方。泄漏不是所有的内存问题,但是值得留意。当你将 LeakCanary 添加到应用程序中时,它会自动开始观察你的 activity 的内存泄漏。有一个我亲眼所见的误用是,他们将 LeakCanary 添加到应用程序中。修复一个或两个泄漏,然后就认为再没有更多的内存泄漏了。它只监视了 activity。如果你在这里使用这个代码( 看幻灯片 ),你可以让它监视 fragment。这并不意味着你不会在别处泄漏内存。activity 和 fragment 是监测的好地方,但如果你没有将观察者设置为对象,你是不知道所有的泄露的。

简单来说,它的工作原理很酷。作为你引用的任何对象的弱引用:将其附加到你不再被引用的内容中。你把它放在 destroy 代码段。然后它做垃圾回收。如果对象仍然存在,这就是内存泄漏,所以它知道什么对象依旧存在。它给你那个 home fragment 现场的相关引用。我觉得这很难理解(*有些人认为这很简单,有人认为这很难。)

这里有个 view 的例子来做点简单说明( 见幻灯片 )。你从底部开始(这就是泄露的东西)。我有 home fragment。 它被 pin grid fragment 引用 - pin grid fragment 是这个对象的父亲。然后我们有这个奇怪的$ 0 - 它解释说,这是一个可运行的对象。对象内有一个处理程序包含一个 runnable。这段代码(这不是我的),它是 Android 操作系统的,是处理程序的代码。处理程序有个 runnalbe 正在运行。我需要确保处理程序不再保留 runnable。在这种情况下,我可以在视图的 destroy 中清除所有的 runnable 和处理程序,这将修复这个内存泄漏。

WeakHandler

你还可以使用这个随机工具 WeakHandler,这使得处理程序引用都是弱引用。如果你触发一个垃圾回收,就可以回收它们。它的缺点是可以被垃圾回收 - 如果你不希望它们被垃圾回收,那可能会出现意想不到的事情。值得注意的是,我遇到的大多数内存泄漏都是无效的,它通常是一个正在运行的 non-missed 的类持有外部类 (这是最常见的地方) 。对于你的内存泄漏,还需要一个 bug 分类的方法。没有什么比你手机上有 70 个内存泄漏, 而你不知道下一步该做什么更糟糕了。作为一个团队,弄清楚当我们发现内存泄漏时要做什么,总是一个好主意。

UI

我们都知道我们一直深陷泥潭。Activity 是旧标准。因为你想重用,所以有了 fragment。但是最后我们用 fragment 把 UI 显示做的异常复杂。试试另一种方法,基于视图的架构,它更流行。在基于视图的架构里,你有一个框架布局,而不用处理任何原生的 Android navigation 的东西,你可以用你想要的视图替换内部的框架布局里的任何东西。希望这能够解决 fragment 的复杂性。

fragment 已经被简化了,而且更新了版本,它们现在更加稳定,但是人们依旧争论着需要有基于视图的架构。如果我们遵循这个论点,我们应该看看一些库(图形的底部, 看幻灯片 )。

基于视图的架构

这个架构是由 Mortar 和 Flow 引入的。我相信他们是第一批普及基于视图的架构的库。 Flow 真正地遵循了基于视图的架构,但是它们往往是一起的,而 Mortar 主要是 MVP 模式。当你开始实现基于视图的架构时,请注意这个奇怪的地方。

你还可以找到些更奇怪的地方,那就是如果你的应用是基于 View 的话,你会遇到些随机的问题,因为这个库不是基于 View 的。它是基于 activity 的, 如果你的应用是基于 view 的话,你得自己去解决那些问题。比如基于 View 的标准问题,例如 on-activity 的行为,许可等等。即使是后退按钮和导航,你都不得不自己去解决,只要你是基于 View 的。

Mortar 和 Flow完成基本的导航功能,但它们并不解决所有常见问题(例如屏幕上保存的状态)。

Conductor正是为这些基于 View 的视图而生的,它创建了一个解决方案:比如保存状态,转换等等。但是你仍然会遇到兼容性问题。总的来说,他们是非常好的,他们是架构不可知的,所以你可以采用你自己的 MV。

Scoop 来自 Lyft。他们在产品中使用它。它是经过产品测试的基于视图架构的解决方案。它们不保存状态,所以 Lyft 无法保存状态。在你将要使用基于视图的架构的主要常见问题中,这是最大的问题。切换很容易使用,但也很有限,这对于基于视图的体系结构来说有点令人失望,因为在这种架构下,你往往可以实现很好的切换。

总的来说,如果你不需要保存状态,Scoop 是可用的,最安全的产品。Conductor 也很好。我会推荐这两个库。

模型 视图 表示(MVP)

有几个很好的 MVP 的库。MVP 的基本思想是把逻辑代码分离出来,这样视图部分,Core Android 的东西,会放在一起,然后 presenter 也是分开的,我们可以单元测试这个 presenter。理论上,我们可以改变视图,而不必完全重写业务逻辑。

有很多方法来做 MVP。我推荐的第一个库是 Mosby 。即使你不使用 Mosby,他们也有很棒的教程和 Android 相关的文章( 比如 MVP 应该是什么样的,它如何工作 )。它主要能提供的功能是给你的 presenter 提供视图状态。

Nucleus也很类似。 Mortar ,作为 Mortar 和 Flow 的一部分,是它们早期的版本,它们越升级问题越多。我看到公司常常自己 构建 MVP :在创建时,你将启动你的 presenter; 销毁时,你会停止你的 presenter 。每个 activity 或任何你的视图持有的任何东西都会有一个 presenter。

所有的这些权衡,虽然听起来很简单,当你实际操作一个用例时,有很多边缘案例要考虑。你有你的适配器,你的视图项目。确保每个人理解的都一样,并且找到能够运用 MVP 的地方是最难的部分。但是这样做的最终结果是你可以获得更多的可单元测试代码。你可以获得更稳定的代码。

测试 - 性能

NimbleDroid

我有一堆关于测试的内容,但我不想让你们听三个小时测试的东西,所以我们跳过使用 JUnit 4 进行单元测试。你有一个 Gradle 构建系统,有 Espresso。这些都是标配。性能测试是个非标的工具。

执行性能测试有两种主要的方法。 Google 倾向于主张使用 Systrace 类似的方法来查看丢帧率,他们有一个代码库,可以为你提供几乎能直接工作的代码(但不是很有效)。这允许你进行自动化性能测试,以查看丢帧率是否变化。

NimbleDroid 有一个免费的试用选项,你可以在其中上传 APK,它将自动测试冷启动,你也可以增加些应用程序中的关键流程。他们提供一个函数发生的时间序列图和详细信息。它可以免费进行试用(例如上传你的 APK 并获得冷启动时间,看是否有明显问题)。如果你想使用它来进行回归测试,那么它是很贵的,但它会帮助你意识到,有人做了一个改动,我们的启动时间变慢了,或者我们的关键流程慢了。如果性能是一个高优先级的目标,那么使用它是很有效的。

JSON

人们在考虑性能时往往都会想到 JSON。有很多的 JSON 库。我的第一个警告是:人们喜欢纯粹通过性能来看待 JSON 库。这是一个错误。我收到了我最大的请求(150千字节,30,000行,巨大的 JSON 文件)。我分别用 GSON 和 Jackson 解析了它们。它们相差大约 20 毫秒,对于那个巨大的文件来说,这并不疯狂。

我的第一个建议是:更多地关注易于使用的东西,有很好的文档的库。你希望得到支持。你不用花几个星期让开发人员尝试找出原因,就因为 stackoverflow 没有答案。除非你对性能有超高的要求,GSON 和 Jackson 是使用最多的,最受欢迎的,特别是在 Android 上,GSON 更受欢迎。

Moshi 是 Square 采用的库。它跟 GSON 非常相似。我试图就如何使用好 GSON 给出了一些意见。你可以同意或不同意这些观点,但都不会错。

如果你关心 JSON 解析性能,并希望它更快,LoganSquare 是一个很好的选择。它们在编译的时候完成了其他库需要在运行时完成的工作。与其他的库相比,这将使你节约大约 1/4 的时间,或四倍的性能提升。如果你真的关心 JSON 性能,你不应该使用 JSON。

相反,你可以使用 Flatbuffer。 JSON 人类可读,Flatbuffer 不是,但是因为这样,它丢掉了其他的不需要的负担。但是 Flatbuffer 与 JSON 相比,Falbuffer 解析几乎不花时间。Facebook 做了这个转换。他们发现启动时间增加了 10% 到 15%,启动时间有所改善。他们也观察到内存使用效率更高。但是使用起来比 JSON 更难,所以谨慎使用。

数据库 - SQL

对于数据库,我们知道常见的是 SQLite - 标准 Android 库。

SQLBrite 是 SQLite 上一个常见的简单库;它为你提供了数据库的 reactive 接口。你可以监听你的用户。如果你的用户有任何更改,你会收到通知,你可以随即更新用户界面。这是一个非常小的库。和 SQL 兼容的很干净。

SQLDelight 也来自 Square。他们写了很多库。它试图避免成为一个完整的 ORM,因为 ORM 会泄漏太多你的代码,并且往往迫使你做太多的事情,当然它仍然试图使数据库的工作更容易些。它使得 API 类型安全,使得 SQL 语句组织的很好(它尝试使其更容易些,同时不会太重)。

如果你愿意去做一个完整的 ORM,那么有很多很好的库:GreenDAO,OrmLite,DBFlow 是一些比较受欢迎的( 还有许多其他选择 )。他们都会说,它们在性能方便表现最好。每个库都有些图表,这些图表显示它们比其他的方案快 100 倍。我的建议是易用性是第一优先事项,然后再考虑是他们在性能上是不是会更好。

数据库 - NoSQL

Realm 是 NoSQL 的方法。它超级快。与其他可比较的数据库不同,Realm 支持的文档非常多。这可以最终节省你大量的开发时间,而且无所谓数据库类型。

Google 推荐的另一种 NoSQL 方法是 LevelDB。键值对,但是它可以说是 “你能够弄清楚该怎么做,但你必须自己弄清楚每一步”。 Realm db 可以帮助你避免这种情况。

Realm 数据库需要特别注意的地方是它的大小( 我认为我们最初添加它时,我们的应用程序大小增加了一倍 )。原因是它是一个本地库。对于每个芯片架构,它们在你的应用程序中都包含了 Realm 数据库的完整副本。为了避免这种情况,你可以将此代码放入 Gradle( 参见幻灯片中的代码 ),并为每个架构生成一个单独的 APK。你把它分解成多少个版本,大小就会减少多少。这也会使你的内存节省很多。对于任何本地运行的 C++ 代码,这是正确的做法,所以在 Crashlytics 和其他一些受欢迎的库中,你能看到同样的收益。

还有另外一款很酷的 Google Play 商店的应用程序 Native Lib。 - 它在 Play 商店中,它会显示些本机库,以便你可以看到你是否为你的 APK 下载了不适用于你手机的代码库。这样做会减少内存使用。如果你就是在寻找手机上保存数据的方案,你可能希望在手机上存储数据。如果你正在构建一次性的应用程序,请不要保持数据。如果你正在使用 Realm 在存储量很小的手机上构建应用(为什么在这种情况下你的应用需要占用大量的存储)?但总的来说,这是一个非常好的数据库解决方案。

数据库 - 移动平台

另一个方面是移动平台:移动开发人员的梦想,我们不再需要这些服务器指南。我们也可以自己构建应用程序。以前的 Parse 是最好的例子(可能会安息)。

现在移动平台中最有名的就是 Firebase 和 Realm。它们都是 NoSQL 模型,它们有一些查询方面的挑战,但是构建速度非常非常快。非常适合进行同步更新。聊天是最常见的解决方案,你发送聊天消息,突然所有的手机都能获取更新。不必构建数据库,不必拥有服务器,你可以使用其中一个解决方案。它使得构建过程非常迅速,马上完成应用并推向市场。而且性能也特别好。

Realm 与 Firebase 的区别是它有离线优先的优点。它们都可以脱机,但是 Firebase 是事后补救,而 Realm 是事先就设计好了,Realm 在许多方面都支持离线。许多应用程序几乎不需要在线行为。如果你正在考虑运行应用跟踪程序,我们希望同步我们的运行状态,而且我们希望所有功能都能完全脱机运行,之后在线工作也正常。Realm 就会脱颖而出。

Analytics

我喜欢分析。精益创业的说法是。如果你可以测量它,你就可以优化它。如果你没有数字的东西,一切都是随机的,你只能猜想如何使它更好。我喜欢有详细的分析,来了解这个改变是否使事情变得更好?人们是否使用此功能?如何改善它?

Analytics 是封装第三方库的理想选择。如果你封装好了 Analytics,那么你应该能够在不修改任何功能代码的前提下,完全替代你的分析服务。你应该能够很容易地添加一个新的 Analytics 服务,以便它们能同时工作。封装 Analytics 代码是一个很好的实践。

如果你正在添加分析数据,最简单的方法是记录你的屏幕,记录人们浏览过的屏幕,将其放在抽象的 activity 中。这样会很快地获得很多的价值。

我看到人们使用 Analytics 技术的常见错误是增加了太多的 Analytics 。他们会在任何地方添加一千个事件,然后没有人知道这个分析意味着什么。他们没有进行充分的测试,所以你真实的注册只有注册的 2/3。在添加分析时需要非常小心。尝试使用简单的命名和标准。不要使用分析来延迟轻松的决定。如果有一个容易的决定,那么请开始。如果你的分析结果告诉你“人们不喜欢释放内存”,那先假设你的分析是错误的。得出一个错误的结论是很容易的。如果你有一个很重要的结论,首先要做的是确认你的分析代码方面没有什么疯狂的事情。

Firebase

Firebase 曾经是一个实时数据库,然后 Google(混淆我们)开始使用一大堆叫做 Firebase 的工具。Firebase Analytics 是所有 Firebase 工具的基础。Google 意识到 iOS 和 Android 开发人员正在解决同样的问题。他们正在使用第三方服务并且通过付费来解决所有这些问题。他们认为,我们可以使构建应用程序更加容易,而且构建应用程序更容易,赚的钱就更多。他们做了这些工具的竞品。迫使它们更好用,谷歌试图使分析工具成为所有的工具的基础。这样做的愿景是,如果你收到崩溃报告,看到你的分析数据,你可以按照崩溃的投资回报率给它们排序。你的通知系统也参与其中,你可以发送通知给那些碰到最昂贵的崩溃的客户,并告诉他们一些免费的折扣。我们知道你即将购买,因为你是一个高价值的崩溃。

这是个很酷的愿景。还没有实现,实话实说。有些工作正常,有些还在开发中,这不是谷歌最高的优先级的任务。但是很多工具还是很好的(不如竞争对手的工具)。 Analytics 虽然是免费的。但是事件不受限制。没有太多的理由不使用它。

另一个流行的是 Google Analytics(分析)。它很容易地获得许多关于用户的基本信息。这是我看到的唯一一个提供很酷的行为流程图的工具,在那里你可以看到人们在你的事件之间切换。它还是有点过时了,其记录事件的风格比所有其他分析工具更旧。它也是免费的,Firebase 意在替换它。

A / B 测试

我个人认为 A / B 测试被过度宣传。通常它被用于慢速学习,以便你了解的更清楚,如果是简单的命名规则就不适用了,当然你可以将其投放到用户手里,你会发现,100 个用户的样本中,55% 偏好了这一选择。这就是你通常看到的 A / B 测试。

它很容易产生 Bug。基本上,A / B 测试中应用程序版本数是你应用程序中的 A / B 测试数加 2。如果你的应用程序中有 3 个 A / B 测试,那么就有 8 个不同版本应用程序一起工作。你可能没有测试各种不同版本的应用程序。有时候你可能会发现因为这些问题,往往会导致重要的决定不太容易做了。

我的解决方案是用户分析服务。 Mixpanel 具有非常好的 A / B 测试工具,而且和你的分析工具兼容。有许多工具用于 A / B 测试。我想说最有名的是 Optimizely 和 Apptomize。Optimizely 更适合网页( 他们的价格 都有点神秘)。他们帮助你提供不同的版本,告诉你这是一个比另一个有显著的更好的统计学差异的版本。

Firebase Remote Config 在技术上可以用来进行 A / B 测试。它不是用于 A / B 测试的。它是用来在不需要开发人员的更新的情况下,从服务器发送键值对的,但是这能让我们做 A / B 测试。你可以发送两个不同版本的键值对,然后你可以使用代码来决定要做什么。之后,你可以将其传递到你自己的分析界面,并找出解析它的方法。从某个角度说,如果你使用 Firebase 远程配置,你是在创造轮子。

你也可以使用 A / B 测试商店列表。这是值得尝试的,特别是你在不同的国家里测试。这是比较容易的,你可以在那里获得一些收获。

崩溃报告

像分析一样,有一千个解决方案。 我只打算介绍少数几个

人们首先看到,特别是 Android 新手,那就是 Play 商店。每当你遇到崩溃时,你可以选择发送报告。大家都会直接忽略,大约 1% 的崩溃出现在 Play 商店中。有时候,如果你的用户数非常大,而且有些非常神秘的崩溃,那可能值得去看看,因为人们会对发生的事情发表评论。也就是说,你有 1% 的崩溃; “99% 的人说应用很烂,崩溃”。但是每隔一段时间,就会有这样的评论 “我在手机上旋转了屏幕,它崩溃了”( 你好像是,啊,一个开发者,我很感激

Crashlytics 趋势是最受欢迎的。这是 Twitter 的 Fabric Suite 或者说是现在的 Google Fabric Suite 的一部分。它是免费的,并为你提供一个非常好的,高级的,有组织的崩溃视图。你仍然需要自行排序和确定优先级。它有一些问题,很难搜索和查询。我看到人们联合使用 Bugsnag,这样查询和搜索会更好一点。 Bugsnag 是相当不错的,但它不是免费的。

Instabug 和 Telescope。Telescope 是个库。你把它放到 bug 里,作为第三方服务。这些库的优点不是监控 crash,而是让你在问题出现时,摇晃手机来报告问题。这样,当你的团队中的设计师看到错误时,他们不用在 JIRA 里提交 Bug,或者和别人说明所有的步骤然后让别人来报 bug,但是你仍然希望这些不是 crash 的 bug 也能被修复。有这么一个工具,所有的测试用户,alpha 用户,你公司的人,看到错误都能告诉你,这些问题需要修复。

推送通知

作为开发人员,第一反应是使用 GCM 或现在的 Firebase Cloud Messaging,这些库正在重组。但是这些工具对营销人员不友好。最简单的情况是,如果你已经有了很好的分析服务,Firebase 和 Mixpanel(以及其他许多库)都可以用来发送通知。你可以根据你的 activity 发送消息。可以这样设计,一个从来没有发生过购买的人,做了三次搜索,这时你可以给他们发送一个通知,建议他们买些东西。这是最简单的情况。

有时你会想要一些更深入的东西。Urban Airship 的推送通知特别专业,这是他们的主要方向。他们发现,“人们只会看到通知的前 60 个字符”,我们都会收到这样的通知,你只能看到前面几个字。就像,“你不会相信这个…”,它被截断了。然后你点击它,你被带到一个随机的屏幕里,你甚至不知道推送通知的内容是什么。Urban Airship 很好,他们帮助你思考这样的事情,给你更多的细微差别提示,思考如何能更好地推出通知服务。

Kahuna 很受欢迎,有很多人都在使用它,但我会强烈反对。他们的想法很棒。通过借助 AI 来帮你确定哪种推送方式更合适,是发送电子邮件,还是发送短信或者是推送通知。AI 计算出最好的推送时间,并建议通知上需不需要添加花朵。这部分他们还没有实现。但他们现在会做些文字上的变化。他们试图让通知受人喜爱,尽可能地推送最合适的通知,想法很酷,希望它能很快实现。但是现在,现实实现中,他们遇到了很多问题,用户的通知被发送给错误的用户。用户被合并在一起,视为一组。所以使用时请小心。有些人用的很好。但我被坑了。

更轻松

有很多伟大的工具能使你的开发更容易些。

一个工具是 Butter Knife(@indVView)。它使你的代码更漂亮。你可以使用 @BindView 通过 ID 查找视图,而不必遍历所有的视图。Zelezny,是一个Android Studio 插件。把它放进 Layout 中,它会自动生成 BindViews 和 OnClicks。如果你以前一直是手敲代码,它会节省点时间。最大的限制是 annotation 的处理会破坏增量编译。如果你有 Butter Knife,那么你可能会比没有 Butter Knife 时的增量编译慢些。对我个人而言,我喜欢所有的 annotation 处理工具,船已航行。我已经接受了 annotation 处理器打破我的增量编译的现实。我听说有人建议将它们全部放在同一个模块中可以解决这个问题。这是唯一的缺点,许多 annotation 处理都会有这个问题。也许有一天这个问题会被修复。 JRebel 声称一些特定版本的增量编译已经修复了。除此之外,Butter Knife 是最好的选择。

Hugo 是个 Jake Wharton 的库(* 当我说 Jake Wharton,一半的时候是指 Square,它们是同一个意思*)。它是一个轻量级的库,你可以在方法之上执行 @Debug.Log,然后打印出该方法花费的时间,以及参数。它特别适用于现场性能记录。 “我需要缓存这个变量吗?它被调用太多了以至于变慢了吗?”你可以看到,“不,这只花了 10 毫秒,我应该把它放在一个后台线程上,或者花了不到一毫秒,我们不用担心这个”。它很容易纳入你的代码,并迅速获得相关数字。

Dart & Henson,你有 intents ;不需要使用键值映射,它给你应该有的值。它做了点 annotation 的映射来展示 intents 的值是什么。我更喜欢的另外一种理解方法是你正在调用的 activity 的静态 intents 。这样,你可以传入你想要的参数,这样就解决了神秘的键值对的问题。它使得代码更加紧密,这样可以防止错误。

如果你喜欢 lambdas,你应该使用 Retrolambda。需要注意是它产生四种方法,而不是正常的匿名类。我认为使用 Retrolambda 会使得代码不易读,这是你必须做出明智决定的地方。

更困难(初期)

我们来谈一谈哪些库会让开发变得更加困难,或者说开始的时候更困难。但总的来说,这些都是好工具。

RxJava

RxJava,对于那些没有听说过的人来说,这个库的想法是,过去的代码从 A 点开始,到 B 点结束。但在 Android 世界中,移动开发世界中,这一切就都不一样了。 *你从 A 点开始。然后人们点击某些东西,所以你必须做些别的事情来响应。然后一个通知进来,你必须又做些事情。然后数据库请求出现了。Reactive 努力使你的代码能够对你的应用程序中的发生的事情做出反应,帮助你更好的组织它们,而且方便移动。

起初很难,因为它有一个学习曲线。如果你正在看代码,特别是对于没有接触过 RxJava 的人来说,会有许多不清楚的地方。最简单的就是网络。但是,如果你有几个标准的例子,你使用这些案例,并确保是最佳的做法,情况就会不一样了。当你开始拥有这些功能时,它们非常强大,你可以将其运用于应用程序中的任何地方,但是当你这样做的时候,每当雇用新的开发人员,你将不得不教会他们每个 activity 是怎么工作的,这需要很小心。

此外,它很容易用错。即使是关于 RxJava 的许多会议都会漏掉一些最佳做法。例如,如果你不取消订阅网络呼叫,那么你会被回调,这时可能会发生崩溃,因为屏幕已经不存在了。谨慎地使用它,总体上来说它还是很好的。

Kotlin

当我说小心使用非内建语言或者说新语言不寻常的地方时,我想说的就是那些你能看到的不寻常的地方。 Kotlin 生成了更整洁的代码。这有好处。使你的代码更容易阅读,也会使没有意义的东西少一些,这是你需要的核心东西。它也隐藏了指针的概念。

最大的缺点是它会随机地破坏事情,如果有什么事情发生,你都会怀疑 Kotlin。这可能是 Kotlin 的错,可能不是,但是都会花掉开发人员的许多时间,来弄清楚到底是不是 Kotlin 的错。你需要更新 Gradle 的构建,然而这依旧不奏效。这可能是 Kotlin 的错,也可能不是 Kotlin 的错,但是你都不得不重新检查 Kotlin。

同样的情况是,你的 Android Studio 也会随机崩溃,或者 ProGuard 不工作了,因为它去掉了一些 Kotlin 的类。这些事情经常发生,很难扭转。Kotlin 有很多权衡点。我们在代码中使用它。确实有一些问题,与此同时,了解 Kotlin 的人们的代码审查更快。对于不知道 Kotlin 的人来说,有一个学习的曲线。这是一个权衡。你必须自己决定。

相机

如果你曾经在 Android 中使用过 Camera,而且你采用的是原生的方案,这并不疯狂,你会发现有摄像头 one API 和摄像头 two API,而且摄像头 two API 没有比摄像头 one API 更好,如果你同时支持新旧设备,你必须使用摄像头 one API,除非你只打算在非常新的设备上正常运行。我的第一个建议是,如果你有使用相机的场景,构建一个 intent。让其他人的相机应用来解决你的问题,如果这不是你的核心场景的话。

如果不是这种情况,有一个名为 Material Camera 的库,我以前 fork 过。你可以添加自己的外观。它帮助你创建相机。解决问题。但是当你按照本教程进行首次设置后,横向显示时,图片会颠倒,你不得不在每个手机上都进行测试,因为他们会以不同的方式安装相机。还有很多边界案例要考虑。Material Camera 是伟大的,它已经把这些情况都解决了。它也支持视频。这是视频模式。你可以改变它上面的 UI,效果很好。再说一次,如果 Camera 是你非常核心的用例,那么你应该重新构建它,这只是个折衷的方案。

我使用的每个相机应用都有裁剪功能,这个功能很可怕。我不知道是什么原因。你试图剪裁,突然间你的视频被剪掉了中间部分。有一个很好的库叫做 “Android Crop”。它提供了一个非常简单的新的 activity 来完成剪裁。

全球思考

作为 Android 的开发人员,我们需要考虑到世界各地的所有开发者。如果你正在为世界各地的开发人员做些开发工作,有些事情你必须考虑,比如网络仿真:你希望能够在低质量网络上进行测试。Android 上做到这点比 iOS 难。仿真器技术可以提供本地仿真器 AVD,但通常情况下,我的经验是,如果你在模拟器上进行任何 3G 操作,没有应用工作正常。我的一些应用程序有时候能在 3G 上正常工作。

我知道的最成功的工具是 Charles 代理。你可以配置经过某个代理。这很容易设置。你可以告诉代理,下载速度应该是多快。但仍然有一个挑战,你需要知道网络可能有多快。比如说像巴西的 3G 网络,几乎是一个无意义的声明 - 3G 在巴西各处都不一样,在各地都是非常不同的。某些时候,你必须尝试找一些数字,选择一些数字。

外面有些资源,但是选择参数是挑选网络仿真最困难的部分之一。有一个名为 Augmented Traffic Control 工具,它来自 Facebook。它允许你连接到服务器或设置路由器,你可以设置配置文件 - 当你连接到路由器时,你的互联网应该有多快。如果你有非开发人员为你测试,他们仍然可以连接到这个 WiFi 网络并设置他们拥有的连接级别。产品经理和测试人员一般也应该考虑质量较差的网络。 ATC 服务器很好用。

我相信新的 Android O 暗示他们会有类似于 AutoFitTextView 的东西,但现在这只是一个库,只要文本对于文本框来说太大,文本就会缩小。如果你正在翻译德语,它的很多字母比英文还是要大一些,那么它会把它缩小到框中。这不是你的第一个翻译解决方案,但最好让它们缩小到文本框的大小,而不是填满整个屏幕并覆盖所有内容。它将调整你的文本大小(更改你的文本大小来适应),这是一个很好的安全的翻译。

YearClass 是 Facebook 的另一个库。它会告诉你,运行你产品的最新的手机生产年份是多少。如果我们说 2015 年是最高的年份,那你就不用关心 2016 年制作的手机上的一些特别的事情。从分析角度来说,这是最好的 - 比如这个崩溃是,发生在 Android OS Marshmallow 上,所有的手机都是低功耗的手机,有时候会发生这种情况。知道一下 crash 在不同年份的手机上的发生概率可以帮你对这个 crash 有更深的了解。

Connection 类是理解用户连接质量的一个非常好的工具(* 这是我在开始时推荐的封装样本类)。它对网络进行分类。不是分成 4G 3G,因为它们变化很大,它依据的是带宽,分为优秀,好,中度或差,或未知。它通过采样下载速度来分类。然后它会移动平均值。这样做的价值是,例如,你是一个显示许多图像的图像网站,你可能希望在较差的网络上降低图像质量,或着执行其他操作。预先知道带宽可以做许多事情。

最大的警告是它的抽样可能是不合时宜的。你能做的事情是让它们开始采样和停止采样。比如,当我打开应用程序时,开始采样,当我关闭应用程序时停止。它们做的事情是查看你下载的数据量,每秒刷新一次。如果用户将你的应用程序打开,并且没有进行任何操作,他们会认为你的网络慢的可怕。我们所做的是,你可以在网络调用或者图像调用的中间启动它,这样做的效果很好。除此之外,这个库对你的网络带宽了解的很准确。

About the content

This content has been published here with the express permission of the author.

 

 

来自:https://academy.realm.io/cn/posts/tools-and-libraries-for-common-android-problems/

 

关注代码技巧 回复19领350本编程书籍

代码技巧

查 看学习编程5个常见的疑问