Skip to content

Commit

Permalink
Merge branch 'master' of github.com:bboyfeiyu/android-tech-frontier
Browse files Browse the repository at this point in the history
  • Loading branch information
hehonghui committed May 1, 2015
2 parents f35501a + 3c6ed23 commit 7b0fe9a
Show file tree
Hide file tree
Showing 10 changed files with 1,508 additions and 5 deletions.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@
* [已完成文章列表](#articles)

## 参与步骤

> 注意事项中有详细说明,这里只是简要地介绍步骤
1. 将该项目fork到自己的github;
2. 在对应期数文件夹里(例如 issue-2,代表第二期 )创建一个markdown文件,文件命名格式为: 中文标题名 ( 不要有空格,有空格的地方用"-"连接 ) ,比如 Android-MVP模式与实践.md;
3. 将模板[template.md](template.md)中的内容拷贝到你的Markdown文件中,按照模板填写、翻译完内容 (注意 : 文章所需图片请存放到图床上,不要放在仓库中,图片宽度尽量控制在400 px左右);
4. 在 Issue 中认领未进行翻译的文章
4. 完成翻译后将状态修改为"校对中",提交pull request到本项目;
5. 管理员校对完成之后便会发布。

Expand All @@ -23,6 +27,8 @@
1. 在翻译文章时,保留专有名词;
2. 在忠于原文的基础上,进行适当的意译,以适应国人阅读习惯;
3. 当翻译完成后,通读一遍,检查语句是否通顺,有无错别字等问题;
4. 原则上每篇文章都由认领人独立翻译,但如果文章很重要,且译文质量不高,那么将会由管理员指定相关人员进行翻译,最后文章将署名为 XX 和 XX 协同翻译;
5. 若译文质量无法通过审核,由译者提交上来的 pull request 将会被拒绝,希望参与翻译的译者们能够理解;

[参与翻译、校对的流程](翻译项目协作流程.md)

Expand All @@ -46,6 +52,10 @@ https://github.com/bboyfeiyu/android-tech-frontier/issues/1
* 标签: `推荐`, 来源,如`androidweekly`,`android-blog`
* milestone: 设置为当月,如`2015/03`

## issue 相关注意事项
1. issue 原则上于每周日由管理员提出,但参与项目的各位如果发现了优秀的文章,而我们还没有创建相应 issue 的话,则可以提出 issue;
2. 参与者提出 issue 后需要 @管理员(如:@bboyfeiyu 我发现了一篇好文章,求审核),管理员将会对文章进行审核,审核通过后管理员会视实际情况分配翻译任务,**一般情况下会直接指定 issue 提出者进行翻译;**
3. 若参与者提出 issue 后未通过审核,却将文章翻译完成,发出了 pull request,那么文章的 pull request 将不会被处理;此外,若文章译文质量不合要求,也不会被处理;

## 翻译任务跟踪和管理

Expand All @@ -72,6 +82,17 @@ https://github.com/bboyfeiyu/android-tech-frontier/issues/1

<b id="articles" />
## 已完成列表
# 2015.5.3 ( 第八期 )
| 文章名称 | 译者 |
|---------|--------|
| [Android 进行单元测试难在哪-序](issue-8/Android 进行单元测试难在哪-序.md) | [chaossss](https://github.com/chaossss) |
| [Custom-Drawables](issue-8/Custom-Drawables.md) | [SwinZh](https://github.com/SwinZh) |
| [Support Libraries v22.1.0](issue-8/Support Libraries v22.1.0.md) | [tiiime](https://github.com/tiiime) |
| [检测Android应用的启动与关闭](issue-8/检测Android应用的启动与关闭.md) | [xianjiajun](https://github.com/xianjiajun) |
| [开始学习Material Design](issue-8/开始学习Material Design.md) | [xu6148152](https://github.com/xu6148152) |
| [如何在Android上响应各种信息通知](issue-8/如何在Android上响应各种信息通知.md) | [MrLoong](https://github.com/MrLoong) |



# 2015.4.26 ( 第七期 )
| 文章名称 | 译者 |
Expand Down
35 changes: 35 additions & 0 deletions issue-8/Android 进行单元测试难在哪-序.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Android 进行单元测试难在哪-序
---

> * 原文链接 : [Against Android Unit Tests](http://philosophicalhacker.com/2015/04/10/against-android-unit-tests/)
* 原文作者 : [Matthew Dupree](http://philosophicalhacker.com/)
* [译文出自 : 开发技术前线 www.devtf.cn](http://www.devtf.cn)
* 译者 : [Rocko](https://github.com/zhengxiaopeng)
* 校对者: [chaossss](https://github.com/chaossss)
* 状态 : 完成

其实不仅仅只有普通 Android 开发工程师觉得测试 Android 应用很恼火,大牛们也受此困扰已久。例如 Jake Wharton 曾经明确地表示:Android 平台自诞生之初就与应用测试势如水火。Don Felker 和 Kaushik Gopal 也在他们的[博文](http://fragmentedpodcast.com/episodes/1/)里也提出了相同的观点。当然了,他们还提到 Google 的 [IOSched 应用](https://github.com/google/iosched),根本就没有进行过测试,据说 IOSched 还是 Android 开发环境中应用开发的最优集合体呢。IOSched 没有进行测试让我们这些开发者很困扰:1、Google 所谓的“测试是高效地进行 Android 开发中的关键一环”真的不是来唬小孩的吗;2、还是 Google 官方的工程师觉得测试 Android 应用简直就是浪费时间?不管怎样,如果这个世界上最优秀的 Android 开发工程师都觉得在 Android 中进行测试很麻烦,那我们这些小菜鸡玩不好测试也是理所当然的了。

多年以来,Android 开发者们为克服在 Android 中难于进行测试的问题绞尽脑汁。Roboletric 就是这些工程师的智慧结晶,它能让开发者们在 JVM 虚拟机上进行 Android 测试。而最近又有博文开始声讨 Fragment,[个中翘楚 Square 就表示](https://corner.squareup.com/2014/10/advocating-against-android-fragments.html):老子再也不用 Fragment 这种垃圾玩意了,我们要把业务逻辑都转换到新开发的 Mortar & Flow (MVP 开发框架)框架里,用纯 Java 对象进行编程,完全不依赖 Android 平台的 API。毫无疑问,这些 Java 对象在标准的 Java 测试工具中进行测试是非常简单的。

我坚信那些和 Square 站在统一战线上的开发团队肯定也在想办法将 UI 从实际的业务逻辑中剥离为纯 Java对象,为提高应用的可测试性不懈努力。换句话说,我觉得我们可以不在 Android 中进行单元测试,也不用实现依赖于 Android SDK 的测试单元。我们应该做的是重构应用,让我们能够为应用中的代码实现纯 Java 的测试单元,无论最终能不能真正地提高 Android 的可测试性和健壮性,我觉得这都值得一试。

我感觉到这个思路会是治本良方,所以我们要做的,就是将下图这样的 Android 的应用架构

![](http://img.my.csdn.net/uploads/201504/26/1430014189_2164.png)

变成下图这样:

![](http://img.my.csdn.net/uploads/201504/26/1430014189_8490.png)

虽然这个方法可能能从根本上解决问题,但它也有很大的风险,尽管如此,我还是坚持认为这个方法值得一试,因为它能拯救万千挣扎在实现 Android 测试单元的开发者们于水火之中,而且不用强迫他们使用第三方的库,毕竟第三库总会让他们滞后于最新的 Android 系统特性。此外,Kent Beck 认为:可测试性好的代码就是架构优秀的代码,如果他的观点是对的,或许我们还能找到架构应用更好的办法。

在接下来的博文里,我将探索“重构 Android 应用以使它们能轻易地通过标准的 Java 工具进行测试”这个方案的可操作性。

在第一、第二篇博文中,我会侧重阐述在 Android 里进行单元测试为什么会带来如此痛苦的体验。我觉得阻碍 Android 测试方法发展的根本原因就在于:Android 系统本身就难于进行测试。缺乏对 Activity 和 Fragment 的合理注入就是让应用难以测试的根本原因,而且认识到这一点是设计可测试强的应用架构的关键。

在第三篇博文中,我会在细节上探讨一个常见的解耦应用代码和 Android SDK的策略。简单来说,这个策略就是:将所有应用的具体行为交给一个 POJO 对象(Plain Ordinary Java Object)完成,这些 POJO 对象都是 Android 无关的接口的 Android 特定实现。

在第四篇博文中,我会指出实现第二篇博文中提出的策略存在的技术难点,并尝试去挖掘可以解决这些难点的方法。在这些难点中,最大的问题在于内存泄漏和繁复的重用代码。

在最后一篇博文中,我会通过展示我提出的架构为 Android 测试性带来的提高让大家觉得进行这样的技术探索是值得花费时间、精力,并且能获得相应回报的。
2 changes: 2 additions & 0 deletions issue-8/Custom-Drawables.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

>
* 原文链接 : [Custom Drawables](http://www.ryanharter.com/blog/2015/04/03/custom-drawables/)
* 原文作者 : [Ryan Harter](http://www.ryanharter.com/)
* [译文出自 : 开发技术前线 www.devtf.cn](http://www.devtf.cn)
* 译者 : [SwinZh](https://github.com/SwinZh)
* 校对者: [Mr.Simple](https://github.com/bboyfeiyu)
* 状态 : 完成
Expand Down
248 changes: 248 additions & 0 deletions issue-8/Support Libraries v22.1.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
Support Libraries v22.1.0
---

> * 原文链接 : [Support Libraries v22.1.0](https://chris.banes.me/2015/04/22/support-libraries-v22-1-0/)
* 原文作者 : [Chris Banes](https://chris.banes.me/)
* [译文出自 : 开发技术前线 www.devtf.cn](http://www.devtf.cn)
* 译者 : [tiiime](https://github.com/tiiime)
* 校对者: [chaossss](https://github.com/chaossss)
* 状态 : 完成



#Support Libraries v22.1.0
22 Apr 2015

好久不见了啊大家~ 你可能听说了我们已经发布 22.1.0 support libraries 的这个消息,
这可能是目前为止我们对 support library 改动最大的一次更新。

在我们开讲前,建议先读一下 Ian Lake 的这篇官方 [blog][official-blog],里面列出了
这次更新中所有的新特性。

这篇文章我将重点讲解内部运行的方式和原因,尤其是我完成的部分
(因为我非常清楚了解这些)。

---

## AppCompat

先从 AppCompat 说起吧,我们在这个版本中对它做了很大的更新。首先,它的重构...

---


###Refactoring

在之前的版本中进入 AppCompat 唯一的入口 ActionBarActivity 已经被我们抛弃了。
也就是说你以后只能使用一组 Activity 视图层,再也不能像 PreferenceActivity 那样使用它了。

我们现在提取出了所有内部内容,并将它们暴露给一个单一委托 API ,
[AppCompatDelegate][AppCompatDelegate] 。AppCompatDelegate 可以从
任何提供了 [Window.Callback][Window.Callback] 接口的 Android 对象中构造,
例如 Activity 或 Dialog 的子类。你可以使用它的静态方法
[create](https://developer.android.com/reference/android/support/v7/app/AppCompatDelegate.html#create(android.app.Activity, android.support.v7.app.AppCompatCallback)) 创建它。

如果你创建了一个委托,你需要在每次调用它提供的接口时回调到它。
(例如 `onCreate()`),不过这很简单,可以提取到一个基类中。

最终,你可以给所有 Activity 的子类附加任何你想要的 AppCompat 的功能。

如果你打算使用 AppCompatDelegate ,我强烈建议你有空看一眼 AppCompatActivity
的源码。这是一个(极端的)例子介绍了怎样整合 AppCompatDelegate。

大部分人不需要这层自定义,可以像原来那样使用 ActionBarActivity
那样使用 [AppCompatActivity][AppCompatActivity] 这个类就好。

---

###Dialogs

上面刚刚提到了 Dialog ,你应该也想到了我们还加入了什么。在完成重构工作后,
Dialog 很自然就是我们下一步工作对象。实际上从 decor-setup 角度来看,
Activity 和 Dialog 这里有一些小的不同。

这意味着我们终于解决了自 v21 以来 AppCompat 最大的需求:
material styled dialogs (balalalala~)。

我们现在有了新的 [AppCompatDialog][AppCompatDialog] 类,
你应该在在引用(or 关联) `Theme.AppCompat.Dialog` 时使用它。

最后,AppCompat 现在也有了它自己的 AlertDialog 实现,来方便构建
material 样式的 AlertDialog。只要使用
[android.support.v7.app.AlertDialog][AlertDialog] 就好了,它会自己处理细节部分。

有一点要注意,AppCompat 的 AlertDialog 没有实现框架版本所做的一切。
它只暴露了在这个 ‘material 世界’ 中有价值的部分。( (╯°□°)╯︵ ┻━┻ )

---

###android:theme

在进入这部分前,请先阅读这篇文章 [Theme vs Style][theme-vs-style]
了解下将要讲解内容的基础。

在 AppCompat v21 里,我们提供了一个快速方便的方法设置设置 [Toolbar][toolbar]
的主题,使用 `app:theme`

在 v22.1.0 里,我们扩充了它的功能,现在你可以给你的 layout 里的任意视图
设置主题了。只要使用 `android:theme` 这个属性就好了,可以在
compat 和 framework 之间无缝地切换功能。

最好的一点要数它会自动继承父视图的 theme ,并且兼容所有 API v11 以上的设备。
一个例子:

```xml
<Toolbar
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

<!-- This TextView inherits its theme from the parent Toolbar -->
<TextView android:text="I'm light!" />

</Toolbar>
```
对于运行 API v10 甚至更老的设备来说,你也可以使用 `android:theme` 属性,
不过它不会继承父视图 theme 。这就意味着你要么重新考虑你的布局,要么
为每一个子视图都设置上 `android:theme` 属性。(这样做效率真的很低)

如果你感兴趣的话,开启继承父类 theme 的方法在这里
[LayoutInflater.Factory2][LayoutInflater.Factory2]

---

###Widgets

如果读过了 Ian 的文章,你可能看到了和 控件着色 (tinting widgets)相关的内容
(这里还有一些新的内容)。

很好,不过关于这点还有一个变化:我们不会再修改 该平台主题的默认
widget 样式了。也就是说如果你使用这个 widget 的 AppCompat
实现(无论显式还是隐式的),那么你在 v21 版本之前的设备上只能获取到
material 样式。在实践中你应该不会看到有什么不同,
因为我们会自动插入适当的 AppCompat 的实现。

这样我们就解决了已经使用 material 样式但是没有着色的问题。它出现在
widget 的平台实现使用了我们的样式,并且出现在不同的位置之中时,比如
Preferences 。

反之,你将会看到当前平台默认的样式 (Holo,etc)。
虽然这样看起来可能有点奇怪,不过这可比看一个空白未着色的 drawable 好多了。

---

###Theme window features
现在 AppCompat 预测 窗口主题 flag 时会更严格 ,配合框架更密切。

背后的原因是为我们早些时候提到的 dialogs 提供支持。它们大量使用了
AppCompat 之前并没有重视的 `windowNoTitle ` 标志。

升级到 v22.1.0 以后,你可能已经遇到过下面的异常:

IllegalArgumentException: AppCompat does not support the current theme features
我在这里回答了解决办法:
[http://stackoverflow.com/q/29790070/474997][stackoverflow]

---


## v4
support libraries 的老祖宗 support-v4 还在继续增长,添加了一些新内容。

### ColorUtils
[ColorUtils][ColorUtils] 已经从 Palette 中移入到 support-v4里。
它包含了一些非常好的操作颜色的方法。比如,你可以计算在某个背景中,
最小的文本颜色 alpha 值:

```java
int backgroundColor = ...;
int textColor = Color.WHITE;
float minContrastRatio = 4.5f; // We want a minimum contrast ration of 1:4.5

int minAlpha = ColorUtils.calculateMinimumAlpha(
textColor, backgroundColor, minContrastRatio);

if (minAlpha != -1) {
// There is an alpha value which has enough contrast, use it!
return ColorUtils.setAlphaComponent(textColor, minAlpha);
}
```
还有很多方便的方法,比如颜色合成,计算亮度工具等等。更多信息可以
去看文档。

---


### Drawable 着色
Lollipop 中加入的 Drawable 着色的方法非常好用,可以让你动态的处理着色资源。
在 v21 support library 中 AppCompat 有它自己的实现,现在我们将它移入到
support-v4 的 [DrawableCompat][DrawableCompat] 之中让大家都可以使用它。
知道它的工作方式很重要。

```java
Drawable drawable = ...;

// Wrap the drawable so that future tinting calls work
// on pre-v21 devices. Always use the returned drawable.
drawable = DrawableCompat.wrap(drawable);

// We can now set a tint
DrawableCompat.setTint(drawable, Color.RED);
// ...or a tint list
DrawableCompat.setTintList(drawable, myColorStateList);
// ...and a different tint mode
DrawableCompat.setTintMode(drawable, PorterDuff.Mode.SRC_OVER);
```
需要注意下在调用完 [DrawableCompat.wrap()][DrawableCompat.wrap] 之后,
它的返回值和你赋值给它的那个并不是同一个东西。你应该使用
[DrawableCompat.unwrap( )][DrawableCompat.unwrap] 取出原始 Drawable。

在内部,我们将你的 Drawable 包裹在一个特殊的 ‘tint drawable’ (着色 drawable)
之中,它会根据指定的色彩自动更新 Drawable 的滤色器。 允许我们处理
[ColorStateList][ColorStateList] 实例。

---

##Palette
Palette 在这次发布中也获得了一些更新。首先,我们给它加入了新的
[Builder][Palette.Builder] 类来帮助获取 Palette 实例。我们发现
Palette 与日俱增的 ‘把手’ 和 设置 正在将它的 API 变得复杂难懂。
使用 Builders 可以显著缓解这个问题。

更加重要的是第二个改变,我们在很大程度上提升了 Palettes 的生成速度。
在生成 Palette 过程中最耗时的要数 色彩量化这一步,它会读取一张图片中的
所有像素点,并降低颜色深度到一个很小的色彩数 (通常是 16)。

在这次更新中,我们使用了传统的方式优化色彩量化的性能,比如更少的对象分配,
更合适的数据结构还有降低算法复杂度。成果很显著~

下面是一些测试数据,在一个使用 ART 的设备上性能大概提升 5 到 6 倍,
如果是使用 Dalvik 的设备,效果还会更加明显。

Device | 22.0 | 22.1.0 | Speedup
----------|--------| ------|------
Nexus 6 | 55ms | 8ms |~6x
Nexus 5 | 55ms | 11ms |~5x
Nexus One | 1200ms | 120ms |~10x

> 测试结果并不是很科学,只是给出一个近似的值,不过你懂这个意思的啦。
Cover photo:[Scaffolding][cover] by Brett Weinstein

---

[official-blog]:http://android-developers.blogspot.com/2015/04/android-support-library-221.html
[AppCompatDelegate]:https://developer.android.com/reference/android/support/v7/app/AppCompatDelegate.html
[Window.Callback]:https://developer.android.com/reference/android/view/Window.Callback.html
[AppCompatDialog]:https://developer.android.com/reference/android/support/v7/app/AppCompatDialog.html
[AlertDialog]:https://developer.android.com/reference/android/support/v7/app/AlertDialog.html
[theme-vs-style]:https://chris.banes.me/2014/11/12/theme-vs-style/
[toolbar]:https://developer.android.com/reference/android/support/v7/widget/Toolbar.html
[LayoutInflater.Factory2]:https://developer.android.com/reference/android/view/LayoutInflater.Factory2.html
[stackoverflow]:http://stackoverflow.com/q/29790070/474997
[ColorUtils]:https://developer.android.com/reference/android/support/v4/graphics/ColorUtils.html
[DrawableCompat]:https://developer.android.com/reference/android/support/v4/graphics/drawable/DrawableCompat.html
[DrawableCompat.wrap]:https://developer.android.com/reference/android/support/v4/graphics/drawable/DrawableCompat.html#wrap(android.graphics.drawable.Drawable)
[DrawableCompat.unwrap]:https://developer.android.com/reference/android/support/v4/graphics/drawable/DrawableCompat.html#unwrap(android.graphics.drawable.Drawable)
[ColorStateList]:https://developer.android.com/reference/android/content/res/ColorStateList.html
[cover]:https://flic.kr/p/GbAqX
[Palette.Builder]:http://developer.android.com/reference/android/support/v7/graphics/Palette.Builder.html
[AppCompatActivity]:https://developer.android.com/reference/android/support/v7/app/AppCompatActivity.html
Loading

0 comments on commit 7b0fe9a

Please sign in to comment.