RxAndroid是RxJava的扩展, 优雅地处理异步请求. RxAndroid配合Lambda表达式, 精简处理回调, 使程序更具备可读性. Rx做为Android最优秀的开源库之一, 极大地提升生产力, 咱们须要掌握. 本文由浅入深, 介绍一些常见的使用方法, 并附有源码.java
更多: http://www.wangchenlong.org/react
本文代码的GitHub下载地址.android
要点包含:
(1) 链式表达式的使用方式.
(2) Lambda的应用.
(3) Rx处理网络请求.
(4) 线程自动管理, 防止内存泄露.
(5) RxBinding绑定控件的异步事件.git

基础
固然, 从一个崭新的HelloWorld项目开始.github
添加Gradle配置.json
1 2 3
|
compile 'com.jakewharton:butterknife:7.0.1' compile 'io.reactivex:rxandroid:1.1.0' |
RxAndroid是本文的核心依赖, 同时添加RxJava. 还有ButterKnife注解库.api
Lambda表达式, 是写出优雅代码的关键, 参考.数组
1 2 3 4 5 6 7 8 9 10 11 12
|
plugins { id "me.tatarka.retrolambda" version "3.2.4" }
android { ...
compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } }
|
Gradle 2.1+
以上, 配置很是简单, 添加一个plugin和一个Java1.8兼容便可.安全
从主MainActivity
跳转至SimpleActivity
.网络
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
|
在SimpleActivity
中, 建立一个观察者, 收到字符串的返回.
建立两个订阅者, 使用字符串输出信息.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
|
在页面中, 观察者接收信息, 发送至主线程AndroidSchedulers.mainThread()
, 再传递给订阅者, 由订阅者最终处理消息. 接收信息能够是同步, 也能够是异步.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_simple); ButterKnife.bind(this);
|
最基础的RxAndroid使用.

更多
咱们已经熟悉了初步的使用方式, 在接着学习一些其余方法, 如
just
: 获取输入数据, 直接分发, 更加简洁, 省略其余回调.
from
: 获取输入数组, 转变单个元素分发.
map
: 映射, 对输入数据进行转换, 如大写.
flatMap
: 增大, 本意就是增肥, 把输入数组映射多个值, 依次分发.
reduce
: 简化, 正好相反, 把多个数组的值, 组合成一个数据.
来看看这个示例, 设置两个不一样类型数组, 做为输入源, 根据不一样状况分发数据.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
|
|
此次简化调用代码, 由于有时候咱们对异常并非很关心,
只要能catch
异常便可, 所以流仅仅关注真正须要的部分.
输入字符串, 变换大写, 输出至控件中显示.
just
能够很是简单的获取任何数据, 分发时, 选择使用的线程.
map
是对输入数据加工, 转换类型, 输入Func1
, 准换大写字母.
Func1
表明使用一个参数的函数, 前面是参数, 后面是返回值.
Action1
表明最终动做, 于是不须要返回值, 而且一个参数.
输入数组, 单独分发数组中每个元素, 转换大写, 输入Toast连续显示.
from
是读取数组中的值, 每次单独分发, 并分发屡次, 其他相似.
输入数组, 映射为单独分发, 并组合到一块儿, 集中显示.
此次是使用just
分发数组, 则分发数据就是数组, 并非数组中的元素.
flatMap
把数组转换为单独分发, Func1
内部使用from
拆分数组.
reduce
把单独分发数据集中到一块儿, 再统一分发, 使用Func2
.
最终使用Action1
显示得到数据. 本次代码也更加简洁.
由此咱们能够观察到, Rx的写法能够是多种多样, 合理的写法会更加优雅.
效果

Lambda
Lambda表达式和Rx很是契合, 能够省略大量的内部类, 如Func和Action.
咱们把上个示例, 用Lambda再写一次, 功能相同.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
|
|
此次没有使用常规的Lambda表达式, 而是更简单的方法引用(Method References)
.
方法引用: 方法参数和返回值与Lambda表达式相同时, 使用方法名代替.
网络请求
Retrofit是网络请求库, 刚推出2.0版本. Rx的一个核心应用就是处理异步网络请求, 结合Retrofit, 会更加方便和简洁. 参考.
引入库
1 2 3 4 5 6 7
|
compile 'com.android.support:recyclerview-v7:23.1.1' |
recyclerview
和picasso
为了显示. retrofit
系列是网络请求.
主页使用一个简单的列表视图, 展现Github的用户信息.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
|
在列表中提供点击用户信息跳转至用户详情.
NetworkWrapper.getUsersInto(adapter)
请求网络, 设置适配器信息.
关键部分, 适配器, 其中包含ViewHolder类和数据类.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
|
添加数据addUser
, 其中notifyItemInserted
通知更新.
能够自动生成Json解析类的网站.
首先建立`Retrofit``服务, 经过服务获取数据, 再依次分发给适配器.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
|
网络请求没法在主线程上执行, 须要启动异步线程, 如Schedulers.newThread()
.
使用工厂模式ServiceFactory
建立服务, 也能够单首创建服务.
建立Retrofit
服务的工厂类.
这是Retrofit 2.0的写法, 注意须要添加Rx和Gson的解析.
设置网络请求的Url.
显示用户

详情页面与主页相似, 参考代码, 不作细说.
线程安全
Rx的好处之一就是能够防止内存泄露, 即根据页面生命周期, 处理异步线程的结束. 可使用RxLifecycle库处理生命周期.
Activity
类继承RxAppCompatActivity
, 替换AppCompatActivity
.
启动一个循环线程.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
|
继承RxAppCompatActivity
, 添加bindToLifecycle
方法管理生命周期. 当页面onPause
时, 会自动结束循环线程. 若是注释这句代码, 则会致使内存泄露.
RxBinding
RxBinding是Rx中处理控件异步调用的方式, 也是由Square公司开发, Jake负责编写. 经过绑定组件, 异步获取事件, 并进行处理. 编码风格很是优雅.
除了RxJava, 再添加RxBinding的依赖.
Toolbar和Fab, 两个较新的控件.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:orientation="vertical" tools:context=".BindingActivity">
<android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar android:id="@+id/rxbinding_t_toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:popupTheme="@style/AppTheme.PopupOverlay" tools:targetApi="21"/>
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_rxbinding"/>
<android.support.design.widget.FloatingActionButton android:id="@+id/rxbinding_fab_fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" android:src="@android:drawable/ic_dialog_email"/>
</android.support.design.widget.CoordinatorLayout>
|
两个EditText控件, 对比传统方法和RxBinding方法.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="@dimen/activity_margin" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context=".BindingActivity" tools:showIn="@layout/activity_binding">
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/usual_approach"/>
<EditText android:id="@+id/rxbinding_et_usual_approach" android:layout_width="match_parent" android:layout_height="48dp" android:hint="@null"/>
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/reactive_approach"/>
<EditText android:id="@+id/rxbinding_et_reactive_approach" android:layout_width="match_parent" android:layout_height="48dp" android:hint="@null"/>
<TextView android:id="@+id/rxbinding_tv_show" android:layout_width="match_parent" android:layout_height="wrap_content"/>
</LinearLayout>
|
使用ButterKnife注入控件, 使用RxBinding方式绑定控件, 异步监听事件.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
|
/** * Rx绑定 * <p> * Created by wangchenlong on 16/1/25. */ public class BindingActivity extends AppCompatActivity {
@Bind(R.id.rxbinding_t_toolbar) Toolbar mTToolbar; @Bind(R.id.rxbinding_et_usual_approach) EditText mEtUsualApproach; @Bind(R.id.rxbinding_et_reactive_approach) EditText mEtReactiveApproach; @Bind(R.id.rxbinding_tv_show) TextView mTvShow; @Bind(R.id.rxbinding_fab_fab) FloatingActionButton mFabFab;
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_binding); ButterKnife.bind(this);
initToolbar(); // 初始化Toolbar initFabButton(); // 初始化Fab按钮 initEditText(); // 初始化编辑文本 }
// 初始化Toolbar private void initToolbar() { // 添加菜单按钮 setSupportActionBar(mTToolbar); ActionBar actionBar = getSupportActionBar(); // 添加浏览按钮 if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); }
RxToolbar.itemClicks(mTToolbar).subscribe(this::onToolbarItemClicked);
RxToolbar.navigationClicks(mTToolbar).subscribe(this::onToolbarNavigationClicked); }
// 点击Toolbar的项 private void onToolbarItemClicked(MenuItem menuItem) { String m = "点击\"" + menuItem.getTitle() + "\""; Toast.makeText(this, m, Toast.LENGTH_SHORT).show(); }
// 浏览点击 private void onToolbarNavigationClicked(Void v) { Toast.makeText(this, "浏览点击", Toast.LENGTH_SHORT).show(); }
@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_rxbinding, menu); return super.onCreateOptionsMenu(menu); }
// 初始化Fab按钮 private void initFabButton() { RxView.clicks(mFabFab).subscribe(this::onFabClicked); }
// 点击Fab按钮 private void onFabClicked(Void v) { Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "点击Snackbar", Snackbar.LENGTH_SHORT); snackbar.show(); RxSnackbar.dismisses(snackbar).subscribe(this::onSnackbarDismissed); }
// 销毁Snackbar, event参考{Snackbar} private void onSnackbarDismissed(int event) { String text = "Snackbar消失代码:" + event; Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); }
// 初始化编辑文本 private void initEditText() { // 正常方式 mEtUsualApproach.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override public void onTextChanged(CharSequence s, int start, int before, int count) { mTvShow.setText(s); }
@Override public void afterTextChanged(Editable s) {
}
});
// Rx方式 RxTextView.textChanges(mEtReactiveApproach).subscribe(mTvShow::setText); } }
|
Toolbar使用RxToolbar监听点击事件; Snackbar使用RxSnackbar监听;
EditText使用RxTextView监听; 其他使用RxView监听.

OK, That’s all. Enjoy it!
原始地址:
http://www.wangchenlong.org/2016/03/20/1603/207-rxjava-first/
欢迎Follow个人GitHub, 关注个人简书, 微博, CSDN, 掘金, Slides.我已委托“维权骑士”为个人文章进行维权行动. 未经受权, 禁止转载, 受权或合做请留言.