安卓开发常用工具和第三方库汇总
<p>我的名字叫 Ryan Cooke 我在 Pinterest 的核心体验团队工作。今天在这里我会谈论各种 Android 库:它们各自的优点,缺点和其他相关知识。目的是高效地概述尽可能多的库,这样,当你遇到一个问题的时候,你知道这是不是个已经解决的问题?什么样的方案更好?同时也能帮助你避免那些陷阱。</p> <p>选择正确的库意味着你可以拥有一个已经成熟的更好的解决方案,而不是花费三个月来重新构建它。了解这些库是第一步。</p> <p>我听到很多人想要实现第一个库, <em>我们难道不能用 Async 任务或原生的东西来做吗?</em> Google 觉得,如果市面上已经有一个解决方案了,他们就不想建立一个一模一样的竞品。他们在多个地方多次表达过这个想法。但是你应该知道,你还有一些别的选择。</p> <h3>一般提示</h3> <p>库最有价值的地方在于 <strong>可逆</strong> :你将库添加到你的应用程序中,之后也可以将其删除(没有任何开销)。随时都能拿出来。不是所有的东西都可以这样,但如果它可以的话,请把它做成一个库,而不是和你的应用终生绑在一起。</p> <p>一个更好的方法是在把你的库封装起来。如果你自己的类调用了库的方法,那么这样做就有着许多的好处,可以让使用者调用你自己的 API。例如,在某些情况下如果库返回异常,你想在 API 里截获它。你只用修改一个文件。有一个封装器让你的库更易用些。</p> <p>如果你正在做一个库,你的团队里面的某些人可能已经开始使用它了,他们知道该如何调用你的库,而不用你的封装。这个检查样式会在编译的时候抛出异常,或者在应用中当他们为连接类使用 import 语句时,提示他们“不要使用连接类,使用封装的 API”。你还会指出不要在这个特定文件上这样做。如果你不这样做,封装器用处就不大,因为人们最终会绕过它。</p> <p>另外, <strong>对第三方库做单元测试</strong> 也是一个好主意。你需要这些测试,如果你正在使用 Joda-Time 这样的库,你可以使用单元测试来了解它奇怪的边界情况。你甚至可以通过单元测试来了解它的工作原理。你可能会发现,如果你不用 add day 方法而是给今天加一的话,你可能会出现二月三十日的情况。</p> <p>在 Android 的世界中,我们必须考虑 <strong>函数数量限制(64,000)</strong> 。( <em>我在说第三方函数库的函数数量,它们会被精简掉</em> )。有一个网站[函数数量](http://methodscount.com),你可以上传你的库,Gradle 导入语句,然后它会告诉你这个库有多少个方法(这是件很棒的事情,特别是当你想使用该库的时候)。使用 ProGuard,许多库将会变得很小。这个方法使你只会包含库中被引用的部分,但是在使用库之前是很难预测你将要使用的内容的。有些时候你可以这样做,“我知道我只使用库的这个方法”,看看它有多小。</p> <p><em>Dex函数计数</em> 会在你的 gradle 里,你也可以在你自己的编译系统上这么做,跟踪你应用程序中函数的总个数。 <em>Apk-method-count</em> 是一个很棒的工具。你可以拖动你的 APK,看看它有多少个方法(63,905 个方法,我喜欢生活在 64,000 的边缘)。在 MultiDex 限制出现之前,你添加的每个方法仍将减慢那些旧设备的启动时间。虽然你的船已经航行,不受 MultiDexing 的限制,十万种方法和十二万种方法之间还是有差别的。更少的方法总是有好处的。 Instagram 就是以 <em>从库</em> 中提取所需的东西而不是使用完整的库而闻名的。这是一个很好的实践,如果你有精力这样做的话。</p> <p>除此之外,我还建议关注 <strong>流行的成熟库</strong> 。每个月(特别是如果你订阅了 Reddit Android 开发者),你将会听到最新,最酷的库。库越成熟,就会越受欢迎。与现有的项目一起工作,兼容性问题就越少。无论何时遇到问题,stackoverflow 那里都会有答案。</p> <p>另外,请注意特殊的方法。这是不符合 Java 标准的东西。如果你正在构建完全不同的布局,那么很可能会有兼容性问题。这时采用库就会变得更加犹豫。</p> <h3>社交登录</h3> <p>非死book 是社交登录的黄金标准( <em>如果你不喜欢 非死book 的实现,情况只会变得更糟</em> )。他们提供测试用户,你可以使用这些测试账户来测试。不再需要假帐户了,你应该使用他们的测试帐户 - 它们工作的更好。我看过有人犯过这样的错误,你不能假设每个 非死book 用户都有电子邮件。大约 10 到 15% 的 非死book 用户没有电子邮件。如果你期待电子邮件,这可能是 10 到 15% 的注册失败的神秘原因。他们需要密钥散列( <em>这是一个随机序列,某段代码打印出的键值哈希</em> ),所以你不必处理它,不用理会它。如果你想申请些其他的疯狂权限,他们现在已经锁定了这些权限。他们需要先看看你打算如何使用这些权限,如果你有这个疯狂的想法而且应用还没有开发好,请提前告知他们。</p> <p>登录和注册时,请记录你所得到的错误。这是我们如何发现由于没有电子邮件,10 到 15% 的注册失败的方法。有时候记录错误可能是找到你不了解的东西的最有效的方法。</p> <p>还有很多其他登录选项:推ter,LinkedIn,Google。我的心态是(特别是 推ter,LinkedIn),虽然他们很受欢迎,但往往不值得的尝试。你会看到不到 2% 的注册率,除非是一个非常好的场景。 LinkedIn 提供了非常具有挑战性的 API( <em>这不是我原来的单词,但是 PR 告诉我,我应该改变它</em> )。 推ter,他们不提供很多信息,但你可以 <a href="/misc/goto?guid=4959754713679384562" rel="nofollow,noindex">转到此链接</a> , 并且说我需要电子邮件和基本信息,他们会给大家授予权限。但总体来说,除非你的架构非常好,这些都会增加你应用的复杂性,。</p> <p>Google 情况比较复杂。在 Android 上,很多人都会拥有 Google 帐户。如果他们没有 Google 帐户,是非常奇怪的。但是你可以从 Google 登录中获得很多功能 - 你可以获取电子邮件提示和其他东西。此外,登录 UI 是十分丑陋的。还有点慢,所以你必须考虑加载模式的对话框。</p> <h3>联网</h3> <p>如果你使用本地库,那么有两个大名鼎鼎的库:Retrofit,Volley。还有 native HTML URL Connect(通常不推荐)。对于 Retrofit 和 Volley 来说,你经常会看到些比较,你会看到 Volley 比 Retrofit 做的更多(例如图像下载和 neat )。这具有欺骗性。</p> <p>Retrofit 是由 Square 建造的,他们有一个哲学,他们的库会尽可能少做事情。他们试图让库严格地解决具体的问题,解决这个问题时,强制执行良好的实践。Retrofit 可能是他们最好的例子。这段代码( <em>见幻灯片</em> )是我在一个应用程序中使用 Retrofit 的示例,我必须为我的 API 调用创建一个非常干净的接口。</p> <p>Get more development news like this</p> <p>Volley 给你足够的绳子吊死自己。你可以使用 Volley,很容易用错。Retrofit 更好地强化了最佳实践,我喜欢这样的做法。</p> <p>很多时候你会听到 OkHttp:这是真正的幕后大举提升网络性能的功臣。它已经在 Android 4.4 的 native 里面了。</p> <h3>网络调试</h3> <p>考虑到网络调试,你有网络调用正在进行,你想了解发生了些什么。</p> <p>Stetho</p> <p>Stetho 是一个很好的选择。它是 非死book 开发的。它为你的网络调用提供了 Chrome 开发者工具视图。它还提供了许多其他的好东西:可以查看你的数据库,看看那里发生了什么;可以看到你的布局,如果你不知道屏幕上发生了什么。其中需要注意的是,你必须在每次运行时启动它,否则它会自动关闭。虽然时间是准确的,但它会使你网络调用的时间更长。</p> <p>HttpLoggingInterceptor</p> <p>我个人倾向于另一个简单的 HttpLoggingInterceptor。你将拦截器添加到你的网络请求中,并将其打印在日志文件上。你也可以看到一些 JSON 文件。有一堆类似的东西都命名为 logging 拦截器。使用 Square 的标准 HTTP 日志记录可以让你更轻松地浏览,非常方便。</p> <h3>图片</h3> <p>作为在 Pinterest 工作的人,图片很重要。如果你正在做图片相关的应用,你可能希望使用第三方库来处理图片缓存,图片下载和图片大小调整。</p> <p>Picasso,Glide</p> <p>图片处理库里最有名的两个库是 Picasso 和 Glide。他们有着非常相似的接口;对于大多数标准用户来说接口基本相同。</p> <p>Picasso 较小。最新版本从 2,879 行缩小到 849 行。但是,Glide 倾向于提供你想要的每个功能:它可以加载 GIF,也可以显示视频预览图像。</p> <p>如果你正在加载图片,Picasso 比较合适。它更受欢迎:它有更多的文档,更多的支持。两个库都很好。如果你一直都有些奇怪的场景,你可以冒险使用 Glide。如果你的使用场景很标准,Picasso 是一个不错的选择。</p> <h3>提示</h3> <p>我已经提到我在 Pinterest 工作,而且图像对我的工作很重要。我必须扔出一堆关于图像的提示。</p> <p>人们都没有做最简单的事情,因为这些库没有这样做,这件简单的事情就是在列表中预取。每当你滚动列表时,你都会看到图像在加载。如果你预取了下一个或两个图像,那么当你滚动时,将会减少帧丢失。这会给你带来更好的体验,不需要等待加载了。如果你预取的图像太多,资源就会竞争,也不好,但预取下一个或两个图像一定会带来更好的体验。</p> <p>除此之外,这些库都不能解决你图像的内存问题。最简单的做法是禁用图像,然后计算出应用程序中的图像消耗了多少内存。不使用图像,计算出省下的内存消耗。另外,释放没有显示图像的图像,并将图像的大小调整为你显示的尺寸也可以帮助节省内存。 Cloudinary 是一个很酷的托管服务,你可以以特定的分辨率请求图像。他们努力做到这点。但是,当你调整请求的图像大小时,你必须确保你没有通过请求类似的图像来破坏缓存(所以这里有个平衡)。</p> <p>我是 bigHeap 的粉丝。我们的一个的应用程序,使用了 bigHeap 后,内存崩溃降到原来的 1/4。 Google 不鼓励使用它,因为它关闭了在后台的其他应用程序,因此应用程序之间的切换并不是那么好。但在某些时候,这不是你的问题。垃圾回收也需要更长时间,你可以使用它来屏蔽内存问题(你不应该这么做)。一般来说,bigHeap 是好的。如果你去 Play Store,并且搜索 largeHeap,你可以下载一个很酷的应用程序,它会显示你手机上启用了 bigHeap 的应用程序。你会注意到现在几乎每个人都陷入了困境,并且正在使用 bigHeap。</p> <p>当你想到内存和图像时,这里有一个简单的公式。有些人会问,“这是个两千字节的 JPEG,为什么我的实际使用的内存会这么大呢?” 使用的内存是像素宽度乘以像素高度的四倍。这就是你期望的大小。它们的标准格式是 ARGB_8888 - 它用四个字节存储颜色空间。如果你使用 RGB_565,你可以将其减少到两倍。但是颜色彼此会非常相似,你会看到更少的色彩空间,它也不能做 alpha,但它会减少一半的内存使用量。你可以考虑在低端设备或低版本 API 上进行此操作。这是节省内存不足问题的好方法。</p> <p>Fresco</p> <p>非死book 发布了一个神奇的库,解决了 API 21 之前的所有版本的内存不足问题。在 API 21 之前,Android 系统中出现了一个错误,你可以在应用程序内存之外使用其他的内存。但是会带来些奇怪的情况:你的程序在旧设备上没有问题,但在新设备上会表现更糟。因为它加载的方式与其他库非常不同,所以它可以实现渐进式 JPEG 这样的图像,图像在图层中逐渐加载。但是,它们会更深入地耦合在你的应用程序中。借助 Glide 和 Picasso,你可以将其与你的应用隔离的很好。而不使用 imageViews,你必须使用它们的类型 Drawees,并且还会产生更多的孤岛代码。</p> <p>如果你定位较低端的设备,你在旧设备上有更多的内存需求,我建议你使用 Fresco。除此之外,我会坚持 Picasso 和 Glide。</p> <h3>内存 - 泄漏</h3> <p>LeakCanary</p> <p>LeakCanary 是当今内存泄露的神器,它可以帮助你找到内存泄露的地方。泄漏不是所有的内存问题,但是值得留意。当你将 LeakCanary 添加到应用程序中时,它会自动开始观察你的 activity 的内存泄漏。有一个我亲眼所见的误用是,他们将 LeakCanary 添加到应用程序中。修复一个或两个泄漏,然后就认为再没有更多的内存泄漏了。它只监视了 activity。如果你在这里使用这个代码( <em>看幻灯片</em> ),你可以让它监视 fragment。这并不意味着你不会在别处泄漏内存。activity 和 fragment 是监测的好地方,但如果你没有将观察者设置为对象,你是不知道所有的泄露的。</p> <p>简单来说,它的工作原理很酷。作为你引用的任何对象的弱引用:将其附加到你不再被引用的内容中。你把它放在 destroy 代码段。然后它做垃圾回收。如果对象仍然存在,这就是内存泄漏,所以它知道什么对象依旧存在。它给你那个 home fragment 现场的相关引用。我觉得这很难理解(*有些人认为这很简单,有人认为这很难。)</p> <p>这里有个 view 的例子来做点简单说明( <em>见幻灯片</em> )。你从底部开始(这就是泄露的东西)。我有 home fragment。 它被 pin grid fragment 引用 - pin grid fragment 是这个对象的父亲。然后我们有这个奇怪的$ 0 - 它解释说,这是一个可运行的对象。对象内有一个处理程序包含一个 runnable。这段代码(这不是我的),它是 Android 操作系统的,是处理程序的代码。处理程序有个 runnalbe 正在运行。我需要确保处理程序不再保留 runnable。在这种情况下,我可以在视图的 destroy 中清除所有的 runnable 和处理程序,这将修复这个内存泄漏。</p> <p>WeakHandler</p> <p>你还可以使用这个随机工具 WeakHandler,这使得处理程序引用都是弱引用。如果你触发一个垃圾回收,就可以回收它们。它的缺点是可以被垃圾回收 - 如果你不希望它们被垃圾回收,那可能会出现意想不到的事情。值得注意的是,我遇到的大多数内存泄漏都是无效的,它通常是一个正在运行的 non-missed 的类持有外部类 <em>(这是最常见的地方)</em> 。对于你的内存泄漏,还需要一个 bug 分类的方法。没有什么比你手机上有 70 个内存泄漏, 而你不知道下一步该做什么更糟糕了。作为一个团队,弄清楚当我们发现内存泄漏时要做什么,总是一个好主意。</p> <h3>UI</h3> <p>我们都知道我们一直深陷泥潭。Activity 是旧标准。因为你想重用,所以有了 fragment。但是最后我们用 fragment 把 UI 显示做的异常复杂。试试另一种方法,基于视图的架构,它更流行。在基于视图的架构里,你有一个框架布局,而不用处理任何原生的 Android navigation 的东西,你可以用你想要的视图替换内部的框架布局里的任何东西。希望这能够解决 fragment 的复杂性。</p> <p>fragment 已经被简化了,而且更新了版本,它们现在更加稳定,但是人们依旧争论着需要有基于视图的架构。如果我们遵循这个论点,我们应该看看一些库(图形的底部, <em>看幻灯片</em> )。</p> <h3>基于视图的架构</h3> <p>这个架构是由 Mortar 和 Flow 引入的。我相信他们是第一批普及基于视图的架构的库。 Flow 真正地遵循了基于视图的架构,但是它们往往是一起的,而 Mortar 主要是 MVP 模式。当你开始实现基于视图的架构时,请注意这个奇怪的地方。</p> <p>你还可以找到些更奇怪的地方,那就是如果你的应用是基于 View 的话,你会遇到些随机的问题,因为这个库不是基于 View 的。它是基于 activity 的, 如果你的应用是基于 view 的话,你得自己去解决那些问题。比如基于 View 的标准问题,例如 on-activity 的行为,许可等等。即使是后退按钮和导航,你都不得不自己去解决,只要你是基于 View 的。</p> <p>Mortar 和 Flow完成基本的导航功能,但它们并不解决所有常见问题(例如屏幕上保存的状态)。</p> <p>Conductor正是为这些基于 View 的视图而生的,它创建了一个解决方案:比如保存状态,转换等等。但是你仍然会遇到兼容性问题。总的来说,他们是非常好的,他们是架构不可知的,所以你可以采用你自己的 MV。</p> <p>Scoop 来自 Lyft。他们在产品中使用它。它是经过产品测试的基于视图架构的解决方案。它们不保存状态,所以 Lyft 无法保存状态。在你将要使用基于视图的架构的主要常见问题中,这是最大的问题。切换很容易使用,但也很有限,这对于基于视图的体系结构来说有点令人失望,因为在这种架构下,你往往可以实现很好的切换。</p> <p>总的来说,如果你不需要保存状态,Scoop 是可用的,最安全的产品。Conductor 也很好。我会推荐这两个库。</p> <h3>模型 视图 表示(MVP)</h3> <p>有几个很好的 MVP 的库。MVP 的基本思想是把逻辑代码分离出来,这样视图部分,Core Android 的东西,会放在一起,然后 presenter 也是分开的,我们可以单元测试这个 presenter。理论上,我们可以改变视图,而不必完全重写业务逻辑。</p> <p>有很多方法来做 MVP。我推荐的第一个库是 <strong>Mosby</strong> 。即使你不使用 Mosby,他们也有很棒的教程和 Android 相关的文章( <em>比如 MVP 应该是什么样的,它如何工作</em> )。它主要能提供的功能是给你的 presenter 提供视图状态。</p> <p>Nucleus也很类似。 <strong>Mortar</strong> ,作为 Mortar 和 Flow 的一部分,是它们早期的版本,它们越升级问题越多。我看到公司常常自己 <strong>构建 MVP</strong> :在创建时,你将启动你的 presenter; 销毁时,你会停止你的 presenter 。每个 activity 或任何你的视图持有的任何东西都会有一个 presenter。</p> <p>所有的这些权衡,虽然听起来很简单,当你实际操作一个用例时,有很多边缘案例要考虑。你有你的适配器,你的视图项目。确保每个人理解的都一样,并且找到能够运用 MVP 的地方是最难的部分。但是这样做的最终结果是你可以获得更多的可单元测试代码。你可以获得更稳定的代码。</p> <h3>测试 - 性能</h3> <p>NimbleDroid</p> <p>我有一堆关于测试的内容,但我不想让你们听三个小时测试的东西,所以我们跳过使用 JUnit 4 进行单元测试。你有一个 Gradle 构建系统,有 Espresso。这些都是标配。性能测试是个非标的工具。</p> <p>执行性能测试有两种主要的方法。 Google 倾向于主张使用 Systrace 类似的方法来查看丢帧率,他们有一个代码库,可以为你提供几乎能直接工作的代码(但不是很有效)。这允许你进行自动化性能测试,以查看丢帧率是否变化。</p> <p>NimbleDroid 有一个免费的试用选项,你可以在其中上传 APK,它将自动测试冷启动,你也可以增加些应用程序中的关键流程。他们提供一个函数发生的时间序列图和详细信息。它可以免费进行试用(例如上传你的 APK 并获得冷启动时间,看是否有明显问题)。如果你想使用它来进行回归测试,那么它是很贵的,但它会帮助你意识到,有人做了一个改动,我们的启动时间变慢了,或者我们的关键流程慢了。如果性能是一个高优先级的目标,那么使用它是很有效的。</p> <p>JSON</p> <p>人们在考虑性能时往往都会想到 JSON。有很多的 JSON 库。我的第一个警告是:人们喜欢纯粹通过性能来看待 JSON 库。这是一个错误。我收到了我最大的请求(150千字节,30,000行,巨大的 JSON 文件)。我分别用 GSON 和 Jackson 解析了它们。它们相差大约 20 毫秒,对于那个巨大的文件来说,这并不疯狂。</p> <p>我的第一个建议是:更多地关注易于使用的东西,有很好的文档的库。你希望得到支持。你不用花几个星期让开发人员尝试找出原因,就因为 stackoverflow 没有答案。除非你对性能有超高的要求,GSON 和 Jackson 是使用最多的,最受欢迎的,特别是在 Android 上,GSON 更受欢迎。</p> <p>Moshi 是 Square 采用的库。它跟 GSON 非常相似。我试图就如何使用好 GSON 给出了一些意见。你可以同意或不同意这些观点,但都不会错。</p> <p>如果你关心 JSON 解析性能,并希望它更快,LoganSquare 是一个很好的选择。它们在编译的时候完成了其他库需要在运行时完成的工作。与其他的库相比,这将使你节约大约 1/4 的时间,或四倍的性能提升。如果你真的关心 JSON 性能,你不应该使用 JSON。</p> <p>相反,你可以使用 Flatbuffer。 JSON 人类可读,Flatbuffer 不是,但是因为这样,它丢掉了其他的不需要的负担。但是 Flatbuffer 与 JSON 相比,Falbuffer 解析几乎不花时间。非死book 做了这个转换。他们发现启动时间增加了 10% 到 15%,启动时间有所改善。他们也观察到内存使用效率更高。但是使用起来比 JSON 更难,所以谨慎使用。</p> <h3>数据库 - SQL</h3> <p>对于数据库,我们知道常见的是 SQLite - 标准 Android 库。</p> <p>SQLBrite 是 SQLite 上一个常见的简单库;它为你提供了数据库的 reactive 接口。你可以监听你的用户。如果你的用户有任何更改,你会收到通知,你可以随即更新用户界面。这是一个非常小的库。和 SQL 兼容的很干净。</p> <p>SQLDelight 也来自 Square。他们写了很多库。它试图避免成为一个完整的 ORM,因为 ORM 会泄漏太多你的代码,并且往往迫使你做太多的事情,当然它仍然试图使数据库的工作更容易些。它使得 API 类型安全,使得 SQL 语句组织的很好(它尝试使其更容易些,同时不会太重)。</p> <p>如果你愿意去做一个完整的 ORM,那么有很多很好的库:GreenDAO,OrmLite,DBFlow 是一些比较受欢迎的( <em>还有许多其他选择</em> )。他们都会说,它们在性能方便表现最好。每个库都有些图表,这些图表显示它们比其他的方案快 100 倍。我的建议是易用性是第一优先事项,然后再考虑是他们在性能上是不是会更好。</p> <h3>数据库 - NoSQL</h3> <p>Realm 是 NoSQL 的方法。它超级快。与其他可比较的数据库不同,Realm 支持的文档非常多。这可以最终节省你大量的开发时间,而且无所谓数据库类型。</p> <p>Google 推荐的另一种 NoSQL 方法是 LevelDB。键值对,但是它可以说是 “你能够弄清楚该怎么做,但你必须自己弄清楚每一步”。 Realm db 可以帮助你避免这种情况。</p> <p>Realm 数据库需要特别注意的地方是它的大小( <em>我认为我们最初添加它时,我们的应用程序大小增加了一倍</em> )。原因是它是一个本地库。对于每个芯片架构,它们在你的应用程序中都包含了 Realm 数据库的完整副本。为了避免这种情况,你可以将此代码放入 Gradle( <em>参见幻灯片中的代码</em> ),并为每个架构生成一个单独的 APK。你把它分解成多少个版本,大小就会减少多少。这也会使你的内存节省很多。对于任何本地运行的 C++ 代码,这是正确的做法,所以在 Crashlytics 和其他一些受欢迎的库中,你能看到同样的收益。</p> <p>还有另外一款很酷的 Google Play 商店的应用程序 Native Lib。 - 它在 Play 商店中,它会显示些本机库,以便你可以看到你是否为你的 APK 下载了不适用于你手机的代码库。这样做会减少内存使用。如果你就是在寻找手机上保存数据的方案,你可能希望在手机上存储数据。如果你正在构建一次性的应用程序,请不要保持数据。如果你正在使用 Realm 在存储量很小的手机上构建应用(为什么在这种情况下你的应用需要占用大量的存储)?但总的来说,这是一个非常好的数据库解决方案。</p> <h3>数据库 - 移动平台</h3> <p>另一个方面是移动平台:移动开发人员的梦想,我们不再需要这些服务器指南。我们也可以自己构建应用程序。以前的 Parse 是最好的例子(可能会安息)。</p> <p>现在移动平台中最有名的就是 Firebase 和 Realm。它们都是 NoSQL 模型,它们有一些查询方面的挑战,但是构建速度非常非常快。非常适合进行同步更新。聊天是最常见的解决方案,你发送聊天消息,突然所有的手机都能获取更新。不必构建数据库,不必拥有服务器,你可以使用其中一个解决方案。它使得构建过程非常迅速,马上完成应用并推向市场。而且性能也特别好。</p> <p>Realm 与 Firebase 的区别是它有离线优先的优点。它们都可以脱机,但是 Firebase 是事后补救,而 Realm 是事先就设计好了,Realm 在许多方面都支持离线。许多应用程序几乎不需要在线行为。如果你正在考虑运行应用跟踪程序,我们希望同步我们的运行状态,而且我们希望所有功能都能完全脱机运行,之后在线工作也正常。Realm 就会脱颖而出。</p> <h3>Analytics</h3> <p>我喜欢分析。精益创业的说法是。如果你可以测量它,你就可以优化它。如果你没有数字的东西,一切都是随机的,你只能猜想如何使它更好。我喜欢有详细的分析,来了解这个改变是否使事情变得更好?人们是否使用此功能?如何改善它?</p> <p>Analytics 是封装第三方库的理想选择。如果你封装好了 Analytics,那么你应该能够在不修改任何功能代码的前提下,完全替代你的分析服务。你应该能够很容易地添加一个新的 Analytics 服务,以便它们能同时工作。封装 Analytics 代码是一个很好的实践。</p> <p>如果你正在添加分析数据,最简单的方法是记录你的屏幕,记录人们浏览过的屏幕,将其放在抽象的 activity 中。这样会很快地获得很多的价值。</p> <p>我看到人们使用 Analytics 技术的常见错误是增加了太多的 Analytics 。他们会在任何地方添加一千个事件,然后没有人知道这个分析意味着什么。他们没有进行充分的测试,所以你真实的注册只有注册的 2/3。在添加分析时需要非常小心。尝试使用简单的命名和标准。不要使用分析来延迟轻松的决定。如果有一个容易的决定,那么请开始。如果你的分析结果告诉你“人们不喜欢释放内存”,那先假设你的分析是错误的。得出一个错误的结论是很容易的。如果你有一个很重要的结论,首先要做的是确认你的分析代码方面没有什么疯狂的事情。</p> <h3>Firebase</h3> <p>Firebase 曾经是一个实时数据库,然后 Google(混淆我们)开始使用一大堆叫做 Firebase 的工具。Firebase Analytics 是所有 Firebase 工具的基础。Google 意识到 iOS 和 Android 开发人员正在解决同样的问题。他们正在使用第三方服务并且通过付费来解决所有这些问题。他们认为,我们可以使构建应用程序更加容易,而且构建应用程序更容易,赚的钱就更多。他们做了这些工具的竞品。迫使它们更好用,谷歌试图使分析工具成为所有的工具的基础。这样做的愿景是,如果你收到崩溃报告,看到你的分析数据,你可以按照崩溃的投资回报率给它们排序。你的通知系统也参与其中,你可以发送通知给那些碰到最昂贵的崩溃的客户,并告诉他们一些免费的折扣。我们知道你即将购买,因为你是一个高价值的崩溃。</p> <p>这是个很酷的愿景。还没有实现,实话实说。有些工作正常,有些还在开发中,这不是谷歌最高的优先级的任务。但是很多工具还是很好的(不如竞争对手的工具)。 Analytics 虽然是免费的。但是事件不受限制。没有太多的理由不使用它。</p> <p>另一个流行的是 Google Analytics(分析)。它很容易地获得许多关于用户的基本信息。这是我看到的唯一一个提供很酷的行为流程图的工具,在那里你可以看到人们在你的事件之间切换。它还是有点过时了,其记录事件的风格比所有其他分析工具更旧。它也是免费的,Firebase 意在替换它。</p> <h3>A / B 测试</h3> <p>我个人认为 A / B 测试被过度宣传。通常它被用于慢速学习,以便你了解的更清楚,如果是简单的命名规则就不适用了,当然你可以将其投放到用户手里,你会发现,100 个用户的样本中,55% 偏好了这一选择。这就是你通常看到的 A / B 测试。</p> <p>它很容易产生 Bug。基本上,A / B 测试中应用程序版本数是你应用程序中的 A / B 测试数加 2。如果你的应用程序中有 3 个 A / B 测试,那么就有 8 个不同版本应用程序一起工作。你可能没有测试各种不同版本的应用程序。有时候你可能会发现因为这些问题,往往会导致重要的决定不太容易做了。</p> <p>我的解决方案是用户分析服务。 Mixpanel 具有非常好的 A / B 测试工具,而且和你的分析工具兼容。有许多工具用于 A / B 测试。我想说最有名的是 Optimizely 和 Apptomize。Optimizely 更适合网页( <em>他们的价格</em> 都有点神秘)。他们帮助你提供不同的版本,告诉你这是一个比另一个有显著的更好的统计学差异的版本。</p> <p>Firebase Remote Config 在技术上可以用来进行 A / B 测试。它不是用于 A / B 测试的。它是用来在不需要开发人员的更新的情况下,从服务器发送键值对的,但是这能让我们做 A / B 测试。你可以发送两个不同版本的键值对,然后你可以使用代码来决定要做什么。之后,你可以将其传递到你自己的分析界面,并找出解析它的方法。从某个角度说,如果你使用 Firebase 远程配置,你是在创造轮子。</p> <p>你也可以使用 A / B 测试商店列表。这是值得尝试的,特别是你在不同的国家里测试。这是比较容易的,你可以在那里获得一些收获。</p> <h3>崩溃报告</h3> <p>像分析一样,有一千个解决方案。 <em>我只打算介绍少数几个</em></p> <p>人们首先看到,特别是 Android 新手,那就是 Play 商店。每当你遇到崩溃时,你可以选择发送报告。大家都会直接忽略,大约 1% 的崩溃出现在 Play 商店中。有时候,如果你的用户数非常大,而且有些非常神秘的崩溃,那可能值得去看看,因为人们会对发生的事情发表评论。也就是说,你有 1% 的崩溃; “99% 的人说应用很烂,崩溃”。但是每隔一段时间,就会有这样的评论 “我在手机上旋转了屏幕,它崩溃了”( <em>你好像是,啊,一个开发者,我很感激</em> )</p> <p>Crashlytics 趋势是最受欢迎的。这是 推ter 的 Fabric Suite 或者说是现在的 Google Fabric Suite 的一部分。它是免费的,并为你提供一个非常好的,高级的,有组织的崩溃视图。你仍然需要自行排序和确定优先级。它有一些问题,很难搜索和查询。我看到人们联合使用 Bugsnag,这样查询和搜索会更好一点。 Bugsnag 是相当不错的,但它不是免费的。</p> <p>Instabug 和 Telescope。Telescope 是个库。你把它放到 bug 里,作为第三方服务。这些库的优点不是监控 crash,而是让你在问题出现时,摇晃手机来报告问题。这样,当你的团队中的设计师看到错误时,他们不用在 JIRA 里提交 Bug,或者和别人说明所有的步骤然后让别人来报 bug,但是你仍然希望这些不是 crash 的 bug 也能被修复。有这么一个工具,所有的测试用户,alpha 用户,你公司的人,看到错误都能告诉你,这些问题需要修复。</p> <h3>推送通知</h3> <p>作为开发人员,第一反应是使用 GCM 或现在的 Firebase Cloud Messaging,这些库正在重组。但是这些工具对营销人员不友好。最简单的情况是,如果你已经有了很好的分析服务,Firebase 和 Mixpanel(以及其他许多库)都可以用来发送通知。你可以根据你的 activity 发送消息。可以这样设计,一个从来没有发生过购买的人,做了三次搜索,这时你可以给他们发送一个通知,建议他们买些东西。这是最简单的情况。</p> <p>有时你会想要一些更深入的东西。Urban Airship 的推送通知特别专业,这是他们的主要方向。他们发现,“人们只会看到通知的前 60 个字符”,我们都会收到这样的通知,你只能看到前面几个字。就像,“你不会相信这个…”,它被截断了。然后你点击它,你被带到一个随机的屏幕里,你甚至不知道推送通知的内容是什么。Urban Airship 很好,他们帮助你思考这样的事情,给你更多的细微差别提示,思考如何能更好地推出通知服务。</p> <p>Kahuna 很受欢迎,有很多人都在使用它,但我会强烈反对。他们的想法很棒。通过借助 AI 来帮你确定哪种推送方式更合适,是发送电子邮件,还是发送短信或者是推送通知。AI 计算出最好的推送时间,并建议通知上需不需要添加花朵。这部分他们还没有实现。但他们现在会做些文字上的变化。他们试图让通知受人喜爱,尽可能地推送最合适的通知,想法很酷,希望它能很快实现。但是现在,现实实现中,他们遇到了很多问题,用户的通知被发送给错误的用户。用户被合并在一起,视为一组。所以使用时请小心。有些人用的很好。但我被坑了。</p> <h3>更轻松</h3> <p>有很多伟大的工具能使你的开发更容易些。</p> <p>一个工具是 Butter Knife(@indVView)。它使你的代码更漂亮。你可以使用 @BindView 通过 ID 查找视图,而不必遍历所有的视图。Zelezny,是一个Android Studio 插件。把它放进 Layout 中,它会自动生成 BindViews 和 OnClicks。如果你以前一直是手敲代码,它会节省点时间。最大的限制是 annotation 的处理会破坏增量编译。如果你有 Butter Knife,那么你可能会比没有 Butter Knife 时的增量编译慢些。对我个人而言,我喜欢所有的 annotation 处理工具,船已航行。我已经接受了 annotation 处理器打破我的增量编译的现实。我听说有人建议将它们全部放在同一个模块中可以解决这个问题。这是唯一的缺点,许多 annotation 处理都会有这个问题。也许有一天这个问题会被修复。 JRebel 声称一些特定版本的增量编译已经修复了。除此之外,Butter Knife 是最好的选择。</p> <p>Hugo 是个 Jake Wharton 的库(* 当我说 Jake Wharton,一半的时候是指 Square,它们是同一个意思*)。它是一个轻量级的库,你可以在方法之上执行 @Debug.Log,然后打印出该方法花费的时间,以及参数。它特别适用于现场性能记录。 “我需要缓存这个变量吗?它被调用太多了以至于变慢了吗?”你可以看到,“不,这只花了 10 毫秒,我应该把它放在一个后台线程上,或者花了不到一毫秒,我们不用担心这个”。它很容易纳入你的代码,并迅速获得相关数字。</p> <p>Dart & Henson,你有 intents ;不需要使用键值映射,它给你应该有的值。它做了点 annotation 的映射来展示 intents 的值是什么。我更喜欢的另外一种理解方法是你正在调用的 activity 的静态 intents 。这样,你可以传入你想要的参数,这样就解决了神秘的键值对的问题。它使得代码更加紧密,这样可以防止错误。</p> <p>如果你喜欢 lambdas,你应该使用 Retrolambda。需要注意是它产生四种方法,而不是正常的匿名类。我认为使用 Retrolambda 会使得代码不易读,这是你必须做出明智决定的地方。</p> <h3>更困难(初期)</h3> <p>我们来谈一谈哪些库会让开发变得更加困难,或者说开始的时候更困难。但总的来说,这些都是好工具。</p> <p>RxJava</p> <p>RxJava,对于那些没有听说过的人来说,这个库的想法是,过去的代码从 A 点开始,到 B 点结束。但在 Android 世界中,移动开发世界中,这一切就都不一样了。 *你从 A 点开始。然后人们点击某些东西,所以你必须做些别的事情来响应。然后一个通知进来,你必须又做些事情。然后数据库请求出现了。Reactive 努力使你的代码能够对你的应用程序中的发生的事情做出反应,帮助你更好的组织它们,而且方便移动。</p> <p>起初很难,因为它有一个学习曲线。如果你正在看代码,特别是对于没有接触过 RxJava 的人来说,会有许多不清楚的地方。最简单的就是网络。但是,如果你有几个标准的例子,你使用这些案例,并确保是最佳的做法,情况就会不一样了。当你开始拥有这些功能时,它们非常强大,你可以将其运用于应用程序中的任何地方,但是当你这样做的时候,每当雇用新的开发人员,你将不得不教会他们每个 activity 是怎么工作的,这需要很小心。</p> <p>此外,它很容易用错。即使是关于 RxJava 的许多会议都会漏掉一些最佳做法。例如,如果你不取消订阅网络呼叫,那么你会被回调,这时可能会发生崩溃,因为屏幕已经不存在了。谨慎地使用它,总体上来说它还是很好的。</p> <p>Kotlin</p> <p>当我说小心使用非内建语言或者说新语言不寻常的地方时,我想说的就是那些你能看到的不寻常的地方。 Kotlin 生成了更整洁的代码。这有好处。使你的代码更容易阅读,也会使没有意义的东西少一些,这是你需要的核心东西。它也隐藏了指针的概念。</p> <p>最大的缺点是它会随机地破坏事情,如果有什么事情发生,你都会怀疑 Kotlin。这可能是 Kotlin 的错,可能不是,但是都会花掉开发人员的许多时间,来弄清楚到底是不是 Kotlin 的错。你需要更新 Gradle 的构建,然而这依旧不奏效。这可能是 Kotlin 的错,也可能不是 Kotlin 的错,但是你都不得不重新检查 Kotlin。</p> <p>同样的情况是,你的 Android Studio 也会随机崩溃,或者 ProGuard 不工作了,因为它去掉了一些 Kotlin 的类。这些事情经常发生,很难扭转。Kotlin 有很多权衡点。我们在代码中使用它。确实有一些问题,与此同时,了解 Kotlin 的人们的代码审查更快。对于不知道 Kotlin 的人来说,有一个学习的曲线。这是一个权衡。你必须自己决定。</p> <h3>相机</h3> <p>如果你曾经在 Android 中使用过 Camera,而且你采用的是原生的方案,这并不疯狂,你会发现有摄像头 one API 和摄像头 two API,而且摄像头 two API 没有比摄像头 one API 更好,如果你同时支持新旧设备,你必须使用摄像头 one API,除非你只打算在非常新的设备上正常运行。我的第一个建议是,如果你有使用相机的场景,构建一个 intent。让其他人的相机应用来解决你的问题,如果这不是你的核心场景的话。</p> <p>如果不是这种情况,有一个名为 Material Camera 的库,我以前 fork 过。你可以添加自己的外观。它帮助你创建相机。解决问题。但是当你按照本教程进行首次设置后,横向显示时,图片会颠倒,你不得不在每个手机上都进行测试,因为他们会以不同的方式安装相机。还有很多边界案例要考虑。Material Camera 是伟大的,它已经把这些情况都解决了。它也支持视频。这是视频模式。你可以改变它上面的 UI,效果很好。再说一次,如果 Camera 是你非常核心的用例,那么你应该重新构建它,这只是个折衷的方案。</p> <p>我使用的每个相机应用都有裁剪功能,这个功能很可怕。我不知道是什么原因。你试图剪裁,突然间你的视频被剪掉了中间部分。有一个很好的库叫做 “Android Crop”。它提供了一个非常简单的新的 activity 来完成剪裁。</p> <h3>全球思考</h3> <p>作为 Android 的开发人员,我们需要考虑到世界各地的所有开发者。如果你正在为世界各地的开发人员做些开发工作,有些事情你必须考虑,比如网络仿真:你希望能够在低质量网络上进行测试。Android 上做到这点比 iOS 难。仿真器技术可以提供本地仿真器 AVD,但通常情况下,我的经验是,如果你在模拟器上进行任何 3G 操作,没有应用工作正常。我的一些应用程序有时候能在 3G 上正常工作。</p> <p>我知道的最成功的工具是 Charles 代理。你可以配置经过某个代理。这很容易设置。你可以告诉代理,下载速度应该是多快。但仍然有一个挑战,你需要知道网络可能有多快。比如说像巴西的 3G 网络,几乎是一个无意义的声明 - 3G 在巴西各处都不一样,在各地都是非常不同的。某些时候,你必须尝试找一些数字,选择一些数字。</p> <p>外面有些资源,但是选择参数是挑选网络仿真最困难的部分之一。有一个名为 Augmented Traffic Control 工具,它来自 非死book。它允许你连接到服务器或设置路由器,你可以设置配置文件 - 当你连接到路由器时,你的互联网应该有多快。如果你有非开发人员为你测试,他们仍然可以连接到这个 WiFi 网络并设置他们拥有的连接级别。产品经理和测试人员一般也应该考虑质量较差的网络。 ATC 服务器很好用。</p> <p>我相信新的 Android O 暗示他们会有类似于 AutoFitTextView 的东西,但现在这只是一个库,只要文本对于文本框来说太大,文本就会缩小。如果你正在翻译德语,它的很多字母比英文还是要大一些,那么它会把它缩小到框中。这不是你的第一个翻译解决方案,但最好让它们缩小到文本框的大小,而不是填满整个屏幕并覆盖所有内容。它将调整你的文本大小(更改你的文本大小来适应),这是一个很好的安全的翻译。</p> <p>YearClass 是 非死book 的另一个库。它会告诉你,运行你产品的最新的手机生产年份是多少。如果我们说 2015 年是最高的年份,那你就不用关心 2016 年制作的手机上的一些特别的事情。从分析角度来说,这是最好的 - 比如这个崩溃是,发生在 Android OS Marshmallow 上,所有的手机都是低功耗的手机,有时候会发生这种情况。知道一下 crash 在不同年份的手机上的发生概率可以帮你对这个 crash 有更深的了解。</p> <p>Connection 类是理解用户连接质量的一个非常好的工具(* 这是我在开始时推荐的封装样本类)。它对网络进行分类。不是分成 4G 3G,因为它们变化很大,它依据的是带宽,分为优秀,好,中度或差,或未知。它通过采样下载速度来分类。然后它会移动平均值。这样做的价值是,例如,你是一个显示许多图像的图像网站,你可能希望在较差的网络上降低图像质量,或着执行其他操作。预先知道带宽可以做许多事情。</p> <p>最大的警告是它的抽样可能是不合时宜的。你能做的事情是让它们开始采样和停止采样。比如,当我打开应用程序时,开始采样,当我关闭应用程序时停止。它们做的事情是查看你下载的数据量,每秒刷新一次。如果用户将你的应用程序打开,并且没有进行任何操作,他们会认为你的网络慢的可怕。我们所做的是,你可以在网络调用或者图像调用的中间启动它,这样做的效果很好。除此之外,这个库对你的网络带宽了解的很准确。</p> <p>About the content</p> <p>This content has been published here with the express permission of the author.</p> <p> </p> <p> </p> <p>来自:https://academy.realm.io/cn/posts/tools-and-libraries-for-common-android-problems/</p> <p> </p>
本文由用户 rose__123 自行上传分享,仅供网友学习交流。所有权归原作者,若您的权利被侵害,请联系管理员。
转载本站原创文章,请注明出处,并保留原始链接、图片水印。
本站是一个以用户分享为主的开源技术平台,欢迎各类分享!