Android Weekly Issue #235

December 11th, 2016

Android Weekly Issue #235

本期内容包括: 开发一个自定义View并发布为开源库的完整流程介绍; 用AnimatedVectorDrawable实现的动画; 什么样的程序是可测试的; DownloadManager介绍; Okhttp的重试; Android 7取消了file://; Android Studio即将推出的build cache功能; 支持离线模式的app构架; 如何写自定义的lint规则; Epoxy, 一个处理复杂RecyclerView屏的库; FragmentPagerAdapterFragmentStatePagerAdapter的比较等.

ARTICLES & TUTORIALS

Make an android custom view, publish and open source

作者开发了一个环形的SeekBar, 并把它作为一个库发布到了JCenter.

作者首先讲了自定义View的实现:

首先是关于View生命周期的介绍, 在写自定义View的时候有几个关键的生命周期回调需要处理:

作者实现的几个关键步骤讲解:

  • 自定义属性并获取.
  • onMeasure()中控制尺寸.
  • onDraw()中绘制: 避免在onDraw()中分配内存; 用invalidate()方法来激发重绘.
  • onTouchEvent()处理用户手势. 在他的环形SeekBar的实现里, 这里涉及到了点击坐标到角度的转换.

将自定义View库开源到Github:

开源到Github有个好的README很重要, 这里有几个tips:

  • 提供截图, Gif或者Video.
  • 提供安装/使用说明.

    作者自己的库: SwagPoints

发布库:

  • JFrog Bintray注册.
  • 创建repository, package, 和版本号.
  • 生成并上传, 用了这个library.
  • 添加到Jcenter.
  • 被接受之后收到邮件, 就可以使用了.

Animation: Jump-through

AnimatedVectorDrawable实现的一个很fancy的位置标志动画.

What makes Android Apps Testable

如果程序的架构不适合测试, 那么硬要写一些测试很可能就会面临这样的局面: 要么就是发现没法写测试, 要么就是为了写测试而破坏了代码, 做了一些奇怪的事情.

那么到底是什么样的程序才是适合写测试, 或者是可测试的呢?

有一个有趣的定义是seam(接缝), 在接缝处你可以改变程序的行为, 而不用编辑当前程序. 如果程序没有接缝, 你将无法设置测试的初始条件和验证测试结果.

本文中举了一个实际的例子, 开始的时候程序没有seam, 所以导致无法测试, 后来把静态方法改为实例的方法之后, 我们就可以通过Mockito来模拟行为, 设置条件, 最后通过验证某一方法的调用与否来进行验证.

DownloadManager – Part 3

DownloadManager来处理下载.

首先它在设备上有自己的UI, 还有notification, 还有Downloads app能让用户管理下载文件.

我们可以查询到文件的一些信息, 比如MIME type, 文件尺寸, 下载状态等.

我们还可以用getUriForDownloadedFile()方法来获取一个URI, 配合MIME type, 发送Intent, 来打开一个相关的查看程序.

关于储存文件的合适地点:

  • 文件小, 仅app自己使用 -> 私有数据区域(默认行为).
  • 文件大, 仅app自己使用 -> 外部存储的私有数据区域(不需要权限). setDestinationInExternalFilesDir().
  • 文件需要被别的应用访问 -> 外部存储的共有区域, 需要WRITE_EXTERNAL_STORAGE权限. setDestinationInExternalPublicDir().

OkHttp is quietly retrying requests. Is your API ready?

在网路较慢或不稳定的时候, OkHttp有可能会重复发送请求, 直到成功.

这个重试的逻辑是通过RetryAndFollowUpInterceptor.java实现的.

那么, 我们可以关掉这个重试行为吗? 有一些issues就在讨论这个问题: Issue # 1043. 后来有两个pull requests: PR #1259PR #2479改进了这个问题, 减少(但并没有消除)了不必要的retry请求.

全局关闭重试行为: OkHttpClient.Builder .retryOnConnectionFailure()设置为false. 但是注意这样是很粗暴并具有破坏性的, 消除了retry逻辑带来的好处:

  • 如果Url有多个IP, 失败了一个还可以试另一个.
  • 连接池中的连接偶尔会time out, 减少这种意外导致的后果.
  • 可以顺次查找多个代理, 如果都失败了再转向直接连接.

解决真正的问题: 关闭静默重试在某些情形下有帮助, 但是其实它隐藏了真正的问题, 就是你的API是否是幂等的idempotent. server端可以根据客户端的GUID来检测重复, 这样server就不会多次执行操作, 会通知发送者.

File scheme is now not allowed with Intent on N

Android N (Nougat, API 24)开始, 不再允许发送file://的Intent, 将会直接抛出FileUriExposedException异常.

所以当你把targetSdkVersion改为24之后, 你必须要确保你修复了这些问题再发布.

解决方案是什么呢? 用content://, 结合FileProvider:

首先在manifest里面声明:

<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>

然后在res\xml\provider_paths.xml文件里指明路径:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>

最后, 把

Uri photoURI = Uri.fromFile(createImageFile());

改为

Uri photoURI = FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider",
createImageFile());

然后放在Intent里发送就好了.

注意, 如果你的targetSdkVersion还没有更新到24, 那么即便是在Nougat的手机上file://也仍然是能正常使用的.

Use Android Studio Gradle Build Cache for faster builds

Android Studio当前的最新版是2.3 Canary 2. 有一些新的改进, 但是其中最吸引人的是这个build cache. 它会使你的clean build更快.

本文后面解析了build cache的工作原理.

Offline App Architecture, build for the Next Billion

一个好的应用应该在网络不好甚至离线的时候仍然可以使用, 我们应该做些什么呢?

  • 确定连接状况. 可以使用这个network-connection-class. 如果你使用的是Okhttp, 可以加一个Intercepter来进行采样.
  • 有效地缓存. 从网络取数据很慢并且昂贵, 所以有效地利用之前取到的数据是很关键的优化. (Cache-Control, Etag).
  • 在本地操作, 在全局同步. 等网络请求的时候可以先显示本地数据, 而不是loading.
  • 有效地处理线程.
  • 优化图片. 网络不好的时候先用RGB_565, 等网络变好了再取高质量图片.
  • 使用大Cookie. 尽量一次传输更多的数据(big cookie), 而不是频繁发送一些小请求(small cookies).

Writing custom lint rules and integrating them

如何创建自定义的lint规则.

事情的由来是作者发现了一个死循环调用, 然后他想做一个什么标记以防以后其他人会犯同样的错误.

然后他想到的是@Nullable注解, 的检查, 实质是依靠lint来实现的.

于是他自己写了一个自定义的lint规则, 来提示使用用他的注解@CarefulNow标记的方法时应当注意.

详细的实现方式请看原文.

Epoxy: Airbnb’s View Architecture on Android

epoxy是一个Android库, 用来处理复杂的RecyclerView屏. 本文介绍了它在项目中实际的使用.

Adventures with FragmentStatePagerAdapter

可能有很多Android开发者对于

FragmentPagerAdapterFragmentStatePagerAdapter的区别不是太清楚或根本不知道, 本文作者就具体介绍了二者的不同.

基本不同

FragmentPagerAdapter

适用于项目个数确定的情形.

为什么呢? 因为一旦fragment的实例被创建, 它永远也不会从FragmentManager中移除, 直到Activity被销毁.

当Fragment不见的时候, 仅仅是onDestroyView()被调用, 当fragment再次回来时, 再调用onCreateView().

FragmentStatePagerAdapter

当fragment的实例不可达的时候, 实例就会立即从FragmentManager移除. 被移除的fragment实例的状态由FragmentStatePagerAdapter保存, 当你再次回到该项的时候, fragment会重建新实例, 并且状态被恢复. 所以这种adapter适用于项目个数不确定或的情况.

所以使用FragmentPagerAdapter的时候需要注意内存问题.

notifyDatasetChanged()的问题.

notifyDataSetChanged()是用来处理数据集变化的情况, 比如一些项目增删的情况. 这个方法不是用来刷新当前显示的Fragment或其中的Views的.

文章中还有一些关于数据改变实现以及现有issue的讨论. 为了解决issue作者还发布了一个库UpdatableFragmentStatePagerAdapter.

LIBRARIES & CODE

KeepActivitiesTile

一个quick settings tile来开启"Don't keep activities".

WaveLoading

一个波形的loading图, 水面上涨代表loading程度.

coordinators

Simple MVWhatever for Android.

epoxy

一个处理复杂的RecyclerView屏的库.

Screen Record for Android

录屏脚本.

Android Weekly Notes Issue #235的更多相关文章

  1. Android Weekly Notes Issue #230

    Android Weekly Notes Issue #230 November 6th, 2016 Android Weekly Issue #230. Android Weekly笔记, 本期内容 ...

  2. Android Weekly Notes Issue #227

    Android Weekly Issue #227 October 16th, 2016 Android Weekly Issue #227. 本期内容包括: Google的Mobile Vision ...

  3. Android Weekly Notes Issue #237

    Android Weekly Issue #237 December 25th, 2016 Android Weekly Issue #237 这是本年的最后一篇issue, 感谢大家. 本期内容包括 ...

  4. Android Weekly Notes Issue #229

    Android Weekly Issue #229 October 30th, 2016 Android Weekly Issue #229 Android Weekly笔记, 本期内容包括: 性能库 ...

  5. Android Weekly Notes Issue #221

    Android Weekly Issue #221 September 4th, 2016 Android Weekly Issue #221 ARTICLES & TUTORIALS And ...

  6. Android Weekly Notes Issue #219

    Android Weekly Issue #219 August 21st, 2016 Android Weekly Issue #219 ARTICLES & TUTORIALS Andro ...

  7. Android Weekly Notes Issue #236

    Android Weekly Issue #236 December 18th, 2016 Android Weekly Issue #236 本期内容包括: Google的物联网平台Android ...

  8. Android Weekly Notes Issue #234

    Android Weekly Issue #234 December 4th, 2016 Android Weekly Issue #234 本期内容包括: ConstraintLayout的使用; ...

  9. Android Weekly Notes Issue #231

    Android Weekly Issue #231 November 13th, 2016 Android Weekly Issue #231 Android Weekly阅读笔记, Issue #2 ...

随机推荐

  1. 如何一步一步用DDD设计一个电商网站(七)—— 实现售价上下文

    阅读目录 前言 明确业务细节 建模 实现 结语 一.前言 上一篇我们已经确立的购买上下文和销售上下文的交互方式,传送门在此:http://www.cnblogs.com/Zachary-Fan/p/D ...

  2. 恢复SQL Server被误删除的数据(再扩展)

    恢复SQL Server被误删除的数据(再扩展) 大家对本人之前的文章<恢复SQL Server被误删除的数据> 反应非常热烈,但是文章里的存储过程不能实现对备份出来的日志备份里所删数据的 ...

  3. NoSql数据库使用半年后在设计上面的一些心得

    NoSql数据库这个概念听闻许久了,也陆续看到很多公司和产品都在使用,优缺点似乎都被分析的清清楚楚.但我心里一直存有一个疑惑,它的出现究竟是为了解决什么问题? 这个疑惑非常大,为此我看了很多分析文章, ...

  4. 背后的故事之 - 快乐的Lambda表达式(一)

    快乐的Lambda表达式(二) 自从Lambda随.NET Framework3.5出现在.NET开发者眼前以来,它已经给我们带来了太多的欣喜.它优雅,对开发者更友好,能提高开发效率,天啊!它还有可能 ...

  5. Matlab slice方法和包络法绘制三维立体图

    前言:在地球物理勘探,流体空间分布等多种场景中,定位空间点P(x,y,x)的物理属性值Q,并绘制三维空间分布图,对我们洞察空间场景有十分重要的意义. 1. 三维立体图的基本要件: 全空间网格化 网格节 ...

  6. EditText 基本用法

    title: EditText 基本用法 tags: EditText,编辑框,输入框 --- EditText介绍: EditText 在开发中也是经常用到的控件,也是一个比较必要的组件,可以说它是 ...

  7. 【Reading Note】算法读书杂记

    1 排序 排序基本信息 稳定性:排序前大的数在排序后,大的数依然保持不变就是稳定排序,反之不稳定 内外排序:根据待排序的记录是否放在内存里面区分的.诸如:插入排序(直接插入&希尔).交换排序( ...

  8. VB.NET设置控件和窗体的显示级别

    前言:在用VB.NET开发射频检测系统ADS时,当激活已存在的目标MDI子窗体时,被其他子窗体遮住了,导致目标MDI子窗体不能显示. 这个问题怎么解决呢?网上看到一篇帖子VB.NET设置控件和窗体的显 ...

  9. 2-1 Linux 操作系统及常用命令

    根据马哥linux初级视频 2-1.2-2来编辑 1. GUI与CLI GUI: Graphic User Interface CLI: Command Line Interface 注:在Windo ...

  10. 程序员装B指南

    一.准备工作 "工欲善其事必先利其器." 1.电脑不一定要配置高,但是双屏是必须的,越大越好,能一个横屏一个竖屏更好.一个用来查资料,一个用来写代码.总之要显得信息量很大,效率很高 ...