Skip to content

Commit

Permalink
Merge pull request #1 from bboyfeiyu/master
Browse files Browse the repository at this point in the history
update from origin
  • Loading branch information
Rogero0o committed Mar 7, 2016
2 parents 8c67a63 + 1f0928f commit 6a42d55
Show file tree
Hide file tree
Showing 10 changed files with 1,358 additions and 14 deletions.
27 changes: 13 additions & 14 deletions issue-34/在Android开发中使用RxJava.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
- 校对者: [desmond1121](https://github.com/desmond1121)
- 状态 : 完成

[ReactiveX](http://reactivex.io/)是专注于异步工作的API,它将异步事件的处理雨观察者模式、迭代器模式及函数式编程相结合了起来。实时地处理返回数据是在工程中经常出现的情景,所以使用高效、可拓展的方式来解决这种问题非常重要。ReactiveX通过观察者模式以及操作符来提供灵活地处理异步通信的方式,你不用再去关注线程创造与同步这些繁琐的事情。
[ReactiveX](http://reactivex.io/)是专注于异步工作的API,它将异步事件的处理与观察者模式、迭代器模式及函数式编程相结合了起来。实时地处理返回数据是在工程中经常出现的情景,所以使用高效、可拓展的方式来解决这种问题非常重要。ReactiveX通过观察者模式以及操作符来提供灵活地处理异步通信的方式,你不用再去关注线程创造与同步这些繁琐的事情。

##RxJava介绍

[RxJava](https://github.com/ReactiveX/RxJava)是一个开源的实现ReactiveX的工具。这里面有两种主要的类:`Observalbe``Subscriber`。在RxJava中,`Observable`类产生异步数据或事件,`Subscriber`类对这些数据和事件进行操作。正常的工作流程就是`Observable`产生一系列的数据或事件,然后完成或者产生异常。一个`Observable`可以拥有多个`Subscriber`每一个被生成的事件都会出发被绑定的`Subscriber``onNext()`方法。当一个`Observable`生成完所有事件后,所有绑定的`Subscriber``onCompleted()`方法会被调用(在发生异常时会调用`onError()`方法)。现在我们对这两个类有了初步的认识,可以开始了解如何创建与订阅一个`Observer`了:
[RxJava](https://github.com/ReactiveX/RxJava)是一个开源的实现ReactiveX的工具。这里面有两种主要的类:`Observalbe``Subscriber`。在RxJava中,`Observable`类产生异步数据或事件,`Subscriber`类对这些数据和事件进行操作。正常的工作流程就是`Observable`产生一系列的数据或事件,然后完成或者产生异常。一个`Observable`可以拥有多个`Subscriber`每一个被生成的事件都会触发被绑定的`Subscriber``onNext()`方法。当一个`Observable`生成完所有事件后,所有绑定的`Subscriber``onCompleted()`方法会被调用(在发生异常时会调用`onError()`方法)。现在我们对这两个类有了初步的认识,可以开始了解如何创建与订阅一个`Observer`了:

Observable integerObservable = Observable.create(new Observable.OnSubscribe() {
@Override
Expand Down Expand Up @@ -47,7 +47,7 @@
你可以看到,这个`Subscriber`将每一个收到的数据打印了出来。当你创建完`Observable``Subscriber`后,你需要将它们用`Observable.subscribe()`方法连接起来。

integerObservable.subscribe(integerSubscriber);
// Outputs:
// 输出:
// onNext: 1
// onNext: 2
// onNext: 3
Expand Down Expand Up @@ -125,15 +125,14 @@
System.out.println("Complete!");
}

@Override
public void onError(Throwable e) {
}
@Override
public void onError(Throwable e) { }

@Override
public void onNext(Double value) {
System.out.println("onNext: " + value);
}
});
@Override
public void onNext(Double value) {
System.out.println("onNext: " + value);
}
});
// Outputs:
// onNext: 1.0
Expand Down Expand Up @@ -277,9 +276,9 @@ RxAndroid是RxJava的轻量级拓展工具,它提供了运行在主线程上

在订阅Single的时候,只有`onSuccess()``onError()`可以监听。同时你可以调用`Single.mergeWith()`操作符来将多个Single合成一个`Observable`,这个被合成的`Observable`会依次输出所有Single的结果。

##防止内存溢出
##防止内存泄露

我们之前提到,使用`AsyncTask`的一大缺点就是它可能会造成内存溢出。当它们持有的Activity/Fragment的引用没有正确处理时就会这样。不幸的是,RxJava并不会自动防止这种情况发生,好在它可以很容易地防止内存泄露。`Observable.subscribe()`方法会返回一个`Subscription`对象,这个对象仅仅有两个方法:`isSbscribed()``unsubscribe()`。你可以在Activity/Fragment的`onDestroy`方法中调用`Subscription.isSubscribed()`检测是否这个异步任务仍在进行。如果它仍在进行,则调用`unsubscribe()`方法来结束任务,从而释放其中的强引用,防止内存泄露。如果你使用了多个`Observable``Subscriber`,那么你可以将它们添加到`CompositeSubscription`中,并调用`CompositeSubscription.unsubscribe()`结束所有的任务。
我们之前提到,使用`AsyncTask`的一大缺点就是它可能会造成内存泄露。当它们持有的Activity/Fragment的引用没有正确处理时就会这样。不幸的是,RxJava并不会自动防止这种情况发生,好在它可以很容易地防止内存泄露。`Observable.subscribe()`方法会返回一个`Subscription`对象,这个对象仅仅有两个方法:`isSbscribed()``unsubscribe()`。你可以在Activity/Fragment的`onDestroy`方法中调用`Subscription.isSubscribed()`检测是否这个异步任务仍在进行。如果它仍在进行,则调用`unsubscribe()`方法来结束任务,从而释放其中的强引用,防止内存泄露。如果你使用了多个`Observable``Subscriber`,那么你可以将它们添加到`CompositeSubscription`中,并调用`CompositeSubscription.unsubscribe()`结束所有的任务。

##结束语

Expand All @@ -306,4 +305,4 @@ Java 8 引入了Lambda表达式,可惜的是Android不支持Java 8,所以我
() -> v.setEnabled(true));
});

Lambda表达式减少了很多RxJava的样本代码,我强烈推荐将RetroLambda引入工程中使用。它给开发带来的好处不仅仅于RxJava上(你会注意到OnCliclListener也是用Lambda表达式设置的)!
Lambda表达式减少了很多RxJava的样本代码,我强烈推荐将RetroLambda引入工程中使用。它给开发带来的好处不仅仅于RxJava上(你会注意到`OnCliclListener`也是用Lambda表达式设置的)!
101 changes: 101 additions & 0 deletions issue-43/IndeterminateProgressbar解析-Part 2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
IndeterminateProgressbar解析-Part 2
---

> * 原文链接 : [Indeterminate – Part 2](https://blog.stylingandroid.com/indeterminate-part-2/)
* 原文作者 : [Mark Allison](https://blog.stylingandroid.com/)
* 译文出自 : [开发技术前线 www.devtf.cn](http://www.devtf.cn)
* 转载声明: 本译文已授权[开发者头条](http://toutiao.io/download)享有独家转载权,未经允许,不得转载!
* 译者 : [chaossss](https://github.com/chaossss)
* 校对者: [chaossss](https://github.com/chaossss)
* 状态 : 完成




IndeterminateProgressBar 能在用户进行某项不定时长的耗时操作时提供绝佳的用户体验,之前我有教过大家怎么创建[水平的 IndeterminateProgressBar](http://blog.csdn.net/u012403246/article/details/49582789),今天我就来教大家实现圆形的 IndeterminateProgressBar,这个控件将支持 API 11(Honeycomb)以上的设备。

在上一篇博文中我们学习了圆形 IndeterminateProgressBar 的 AOSP 实现方式,以及 AnimatedVectorDrawable 如何被用于显示 VectorDrawable 路径动画以得到圆形 IndeterminateProgressBar 的长度变化动画。在本篇博文中我们将把注意力转移到插值器上,即研究圆形 IndeterminateProgressBar 在显示长度变化动画时,是如何控制圆弧起点和终点的位置的。

不妨直接看 AOSP 的源码吧,[首先看 控制 trimPathStart 的值的插值器](https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/res/res/interpolator/trim_start_interpolator.xml):

```xml
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:pathData="L0.5,0 C 0.7,0 0.6,1 1, 1" />
```

乍一看这代码怎么这么少,那个 PathInterpolator 到底是什么鬼?

PathInterpolator 其实就是 Lollipop 中介绍的描述插值器功能最具代表性的插值器子类,看到这里不要绝望,在以后的博文中我们还会遇到 PathInterpolatorCompat 这个类。

A PathInterpolator takes an SVG pathData parameter which describes a mapping function of the form y = f(x). That sounds rather complex, but it is actually much simpler than it sounds. Effectively it is a square canvas which is one unit in each direction from 0,0 to 1,1. The PathInterpolator works by returning the y value for any given x value. The input values range from 0.0-1.0, so there only stipulation is that each possible value for x can only map to a single value of y – the path cannot double back on itself in the horizontal plane in other words.

PathInterpolator 需要 SVG pathData 参数以描述 y = f(x) 的映射关系,可能听起来有点复杂,但其实它非常简单。实际上,就是一个每个方向上都有一个从 0,0 到 1,1 的单元的方形画布,PathInterpolator 可以根据任意给定的 x 的值返回给定函数所映射的 y 值,其接收的输入的取值范围是 0.0 - 1.0,所以其输入的唯一约定就是:每一个可能的 x 和 y 必须是1对1映射。

如果我们画了一条从 0,0 到 1,1 的直线,实际上就相当于创建了线性插值器(LinearInterpolator),因为每一个 x 的值对应的 y 值都相同。那么上述代码中 pathData 到底做了什么?运用一个有趣的技巧,我们可以创建 VectorDrawable 并添加该 path 元素,然后用 Android Studio 的预览功能就会看到下图:

```xml
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:width="72dp"
android:height="72dp"
android:viewportWidth="1"
android:viewportHeight="1"
tools:ignore="UnusedResources">

<path
android:strokeColor="#0000FF"
android:strokeWidth="0.005"
android:pathData="L0.5,0 C 0.7,0 0.6,1 1, 1" />

<vector>
```

![](https://i2.wp.com/blog.stylingandroid.com/wp-content/uploads/2016/01/trim_start_interpolator.png?w=608)

由图可知,0,0 就是路径的左上角,1,1 就是路径的右下角。当 x = [0.0 - 0.5], y = 0;当 x = (0.5, 1.0],y 值的增长逐渐增加,然后超过中值,增长速率又渐渐变慢,最终为 1.0。其实际作用与 AccelerateDecelerateInterpolator 相同。如果我们研究 trimPathEnd 使用的插值器,会发现这两个阶段完成的工作比使用传统插值器要复杂:

```xml
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:pathData="C0.2,0 0.1,1 0.5, 1 L 1,1" />
```

看起来这段 xml 代码和上面的很类似,但 pathData 对应的值是不同的,不妨再次利用 VectorDrawable 将这个插值器对应的函数图像显示出来:

![](https://i0.wp.com/blog.stylingandroid.com/wp-content/uploads/2016/01/trim_start_and_end_interpolators.png?resize=223%2C300)

图中红色显示作加速的部分,y 值快速增加直到大于中值,然后减缓增大的速率直到值为 1.0,相当于把上面的过程反过来。

trimPathEnd 会控制长度变化动画中圆弧的终点,trimPathStart 则控制该圆弧的起点。利用这些插值器我们可以让圆弧的长度自动变化,以显示长度变化的动画。最终结合旋转动画就可以实现该圆形 IndeterminateProgressbar 的效果,即下面视频展示的效果:

[视频](https://youtu.be/g6Zo6WDS2Gg)

现在我们明白该控件是怎么实现的了,而且 AnimatedVectorDrawable 支持 Android 5.0 以前的版本,因此我们不用担心它的兼容性问题(在写下本文时 VectorDrawableCompat 由于兼容性的问题不是个好选择)。因此我们不需要 VectorDrawable 就可以利用到目前为止学习的知识在 API 11 上实现酷炫的动画效果,在下一篇博文中我将会介绍应该怎么去实现。

因为这篇博文都是基于[ Google 源码](https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/res/res/anim/progress_indeterminate_rotation_material.xml)进行的,所以我就不提供源码了,但后面的文章我保证都会有源码!
Loading

0 comments on commit 6a42d55

Please sign in to comment.