下载好rx rxandroid.jar下载怎么用?

Rx在Android中的最佳实践
By default, RxJava is synchronous
测试起来更方便;使用Observable.from创建observable,所有的subscription将立即触发;不要假设接收的subscription是异步的;
Hot and cold subscriptions
通常,只有observable被订阅(subscribe)时,所有的操作才会被执行;根据不同的实现,有可能每次有新的subscriber都会新创建一个operation,也有可能并不会;.cache操作可以缓存吐出的数据,后面的subscriber都会收到同一个数据;
Use subjects when in trouble
subject既能接收数据,也能吐出数据;
Pay attention to the thread
;但是把切换回主线程放到最后并不一定是最好的;
Read the RxJava wiki and look at the diagrams
Subscribing with Observer vs. Action
使用Action1时如果发生错误,将抛出异常;最好是使用一个公用的ErrorHandler;
Subscriptions leak memory
匿名的observable会持有外部类的强引用,有可能导致内存泄漏;好的办法是每次使用observable,都将最后的subscription都保存起来,然后在合适的时机集中unSubscribe,以避免内存泄漏;
多个source,由快到慢
concat/concatWith,根据参数的顺序,依次把每个observable发射的item拼接起来,形成一个新的序列;参数之间发射的item不会重叠,即第一个observable的所有item发射完之后,第二个observable才会开始发射;
first/takeFirst,从序列中取出第一个item,可以加过滤条件;first在过滤时如果没有满足条件的item,将会抛出异常,而takeFirst不会抛异常,只会调用onCompleted;
两者结合,当第一个满足条件的item取到之后,concat参数中后面的observable将不会被subscribe;如果参数observable都是cold的,那么后面observable的产生操作将不会被执行;运行效果:
使用说明:Rx系列(4)
是RxJava的扩展, 可以优雅地处理异步请求. 以前的文章讲述过一些, 这次再补充些内容, 熟悉RxAndroid的使用方法.
本文源码的GitHub
(1) 链式表达式的使用方式.
(2) Lambda的应用.
(3) Rx处理网络请求.
(4) 线程自动管理, 防止内存泄露.
(5) RxBinding绑定控件的异步事件.
当然, 从一个崭新的HelloWorld项目开始.
添加Gradle配置.
compile 'com.jakewharton:butterknife:7.0.1'
compile 'io.reactivex:rxandroid:1.1.0'
compile 'io.reactivex:rxjava:1.1.0'
RxAndroid是本文的核心依赖, 同时添加RxJava. 还有ButterKnife注解库.
Lambda表达式, 是写出优雅代码的关键, 参考.
id "me.tatarka.retrolambda" version "3.2.4"
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
Gradle 2.1+以上, 配置非常简单, 添加一个plugin和一个Java1.8兼容即可.
从主MainActivity跳转至SimpleActivity.
* 主Activity, 用于跳转各个模块.
* wangchenlong
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
public void gotoSimpleModule(View view) {
startActivity(new Intent(this, SimpleActivity.class));
public void gotoMoreModule(View view) {
startActivity(new Intent(this, MoreActivity.class));
public void gotoLambdaModule(View view) {
startActivity(new Intent(this, LambdaActivity.class));
public void gotoNetworkModule(View view) {
startActivity(new Intent(this, NetworkActivity.class));
public void gotoSafeModule(View view) {
startActivity(new Intent(this, SafeActivity.class));
在SimpleActivity中, 创建一个观察者, 收到字符串的返回.
Observable.OnSubscribe mObservableAction = new Observable.OnSubscribe&String&() {
@Override public void call(Subscriber&? super String& subscriber) {
subscriber.onNext(sayMyName());
subscriber.onCompleted();
private String sayMyName() {
return "Hello, I am your friend, Spike!";
创建两个订阅者, 使用字符串输出信息.
Subscriber&String& mTextSubscriber = new Subscriber&String&() {
@Override public void onCompleted() {
@Override public void onError(Throwable e) {
@Override public void onNext(String s) {
mTvText.setText(s);
Subscriber&String& mToastSubscriber = new Subscriber&String&() {
@Override public void onCompleted() {
@Override public void onError(Throwable e) {
@Override public void onNext(String s) {
Toast.makeText(SimpleActivity.this, s, Toast.LENGTH_SHORT).show();
在页面中, 观察者接收信息, 发送至主线程AndroidSchedulers.mainThread(), 再传递给订阅者, 由订阅者最终处理消息. 接收信息可以是同步, 也可以是异步.
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple);
ButterKnife.bind(this);
@SuppressWarnings("unchecked")
Observable&String& observable = Observable.create(mObservableAction);
observable.observeOn(AndroidSchedulers.mainThread());
observable.subscribe(mTextSubscriber);
observable.subscribe(mToastSubscriber);
最基础的RxAndroid使用.
我们已经熟悉了初步的使用方式, 在接着学习一些其他方法, 如
just: 获取输入数据, 直接分发, 更加简洁, 省略其他回调.
from: 获取输入数组, 转变单个元素分发.
map: 映射, 对输入数据进行转换, 如大写.
flatMap: 增大, 本意就是增肥, 把输入数组映射多个值, 依次分发.
reduce: 简化, 正好相反, 把多个数组的值, 组合成一个数据.
来看看这个示例, 设置两个不同类型数组, 作为输入源, 根据不同情况分发数据.
* 更多的RxAndroid的使用方法.
* Created by wangchenlong on 15/12/30.
public class MoreActivity extends Activity {
@Bind(R.id.simple_tv_text) TextView mTvT
final String[] mManyWords = {"Hello", "I", "am", "your", "friend", "Spike"};
final List&String& mManyWordList = Arrays.asList(mManyWords);
private Action1&String& mTextViewAction = new Action1&String&() {
@Override public void call(String s) {
mTvText.setText(s);
private Action1&String& mToastAction = new Action1&String&() {
@Override public void call(String s) {
Toast.makeText(MoreActivity.this, s, Toast.LENGTH_SHORT).show();
private Func1&List&String&, Observable&String&& mOneLetterFunc = new Func1&List&String&, Observable&String&&() {
@Override public Observable&String& call(List&String& strings) {
return Observable.from(strings);
private Func1&String, String& mUpperLetterFunc = new Func1&String, String&() {
@Override public String call(String s) {
return s.toUpperCase();
private Func2&String, String, String& mMergeStringFunc = new Func2&String, String, String&() {
@Override public String call(String s, String s2) {
return String.format("%s %s", s, s2);
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple);
ButterKnife.bind(this);
Observable&String& obShow = Observable.just(sayMyName());
obShow.observeOn(AndroidSchedulers.mainThread())
.map(mUpperLetterFunc).subscribe(mTextViewAction);
Observable&String& obMap = Observable.from(mManyWords);
obMap.observeOn(AndroidSchedulers.mainThread())
.map(mUpperLetterFunc).subscribe(mToastAction);
Observable.just(mManyWordList)
.observeOn(AndroidSchedulers.mainThread())
.flatMap(mOneLetterFunc)
.reduce(mMergeStringFunc)
.subscribe(mToastAction);
private String sayMyName() {
return "Hello, I am your friend, Spike!";
这次简化调用代码, 因为有时候我们对异常并不是很关心,
只要能catch异常即可, 因此流仅仅关注真正需要的部分.
输入字符串, 变换大写, 输出至控件中显
// 添加字符串, 省略Action的其他方法, 只使用一个onNext.
Observable&String& obShow = Observable.just(sayMyName())
// 先映射, 再设置TextView
obShow.observeOn(AndroidSchedulers.mainThread())
.map(mUpperLetterFunc).subscribe(mTextViewAction)
t可以非常简单的获取任何数据, 分发时, 选择使用的线程.
map是对输入数据加工, 转换类型, 输入Func1, 准换大写字母.
Func1代表使用一个参数的函数, 前面是参数, 后面是返回值.
Action1代表最终动作, 因而不需要返回值, 并且一个参数.
输入数组, 单独分发数组中每一个元素, 转换大写, 输入Toast连续显
// 单独显示数组中的每个元素
Observable&String& obMap = Observable.from(mManyWords)
// 映射之后分发
obMap.observeOn(AndroidSchedulers.mainThread())
.map(mUpperLetterFunc).subscribe(mToastAction)
m是读取数组中的值, 每次单独分发, 并分发多次, 其余类似.
输入数组, 映射为单独分发, 并组合到一起, 集中
// 优化过的代码, 直接获取数组, 再分发, 再合并, 再显示toast, Toast顺次执行.
Observable.just(mManyWordList)
.observeOn(AndroidSchedulers.mainThread())
.flatMap(mOneLetterFunc)
.reduce(mMergeStringFunc)
.subscribe(mToastAction)
这次是使用just分发数组, 则分发数据就是数组, 并不是数组中的元素.
flatMap把数组转换为单独分发, Func1内部使用from拆分数组.
reduce把单独分发数据集中到一起, 再统一分发, 使用Func2.
最终使用Action1显示获得数据. 本次代码也更加简洁.
由此我们可以观察到, Rx的写法可以是多种多样, 合理的写法会更加优雅.
Lambda表达式和Rx非常契合, 可以省略大量的内部类, 如Func和Action.
我们把上个示例, 用Lambda再写一次, 功能相同.
* Lambda表达式写法
* Created by wangchenlong on 15/12/31.
public class LambdaActivity extends Activity {
@Bind(R.id.simple_tv_text) TextView mTvT
final String[] mManyWords = {"Hello", "I", "am", "your", "friend", "Spike"};
final List&String& mManyWordList = Arrays.asList(mManyWords);
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple);
ButterKnife.bind(this);
Observable&String& obShow = Observable.just(sayMyName());
obShow.observeOn(AndroidSchedulers.mainThread())
.map(String::toUpperCase).subscribe(mTvText::setText);
Observable&String& obMap = Observable.from(mManyWords);
obMap.observeOn(AndroidSchedulers.mainThread())
.map(String::toUpperCase)
.subscribe(this::showToast);
Observable.just(mManyWordList)
.observeOn(AndroidSchedulers.mainThread())
.flatMap(Observable::from)
.reduce(this::mergeString)
.subscribe(this::showToast);
private String sayMyName() {
return "Hello, I am your friend, Spike!";
private void showToast(String s) {
Toast.makeText(LambdaActivity.this, s, Toast.LENGTH_SHORT).show();
private String mergeString(String s1, String s2) {
return String.format("%s %s", s1, s2);
这次没有使用常规的Lambda表达式, 而是更简单的方法引用(Method References).
方法引用: 方法参数和返回值与Lambda表达式相同时, 使用方法名代替.
4. 网络请求
Retrofit是网络请求库, 刚推出2.0版本. Rx的一个核心应用就是处理异步网络请求, 结合Retrofit, 会更加方便和简洁. 参考.
compile 'com.android.support:recyclerview-v7:23.1.1'
compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
compile 'com.squareup.picasso:picasso:2.5.2'
recyclerview和picasso为了显示. retrofit系列是网络请求.
主页使用一个简单的列表视图, 展示Github的用户信息.
* Rx的网络请求方式
* Created by wangchenlong on 15/12/31.
public class NetworkActivity extends Activity {
@Bind(R.id.network_rv_list) RecyclerView mRvL
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_network);
ButterKnife.bind(this);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRvList.setLayoutManager(layoutManager);
UserListAdapter adapter = new UserListAdapter(this::gotoDetailPage);
NetworkWrapper.getUsersInto(adapter);
mRvList.setAdapter(adapter);
public interface UserClickCallback {
void onItemClicked(String name);
private void gotoDetailPage(String name) {
startActivity(NetworkDetailActivity.from(NetworkActivity.this, name));
在列表中提供点击用户信息跳转至用户详情.
NetworkWrapper.getUsersInto(adapter) 请求网络, 设置适配器信息.
关键部分, 适配器, 其中包含ViewHolder类和数据类.
public class UserListAdapter extends RecyclerView.Adapter&UserListAdapter.UserViewHolder& {
private List&GitHubUser& mU
private NetworkActivity.UserClickCallback mC
public UserListAdapter(NetworkActivity.UserClickCallback callback) {
mUsers = new ArrayList&&();
mCallback =
public void addUser(GitHubUser user) {
mUsers.add(user);
notifyItemInserted(mUsers.size() - 1);
@Override public UserViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View item = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_network_user, parent, false);
return new UserViewHolder(item, mCallback);
@Override public void onBindViewHolder(UserViewHolder holder, int position) {
holder.bindTo(mUsers.get(position));
@Override public int getItemCount() {
return mUsers.size();
public static class UserViewHolder extends RecyclerView.ViewHolder {
@Bind(R.id.network_item_iv_user_picture) ImageView mIvUserP
@Bind(R.id.network_item_tv_user_name) TextView mTvUserN
@Bind(R.id.network_item_tv_user_login) TextView mTvUserL
@Bind(R.id.network_item_tv_user_page) TextView mTvUserP
public UserViewHolder(View itemView, NetworkActivity.UserClickCallback callback) {
super(itemView);
ButterKnife.bind(this, itemView);
itemView.setOnClickListener(v -&
callback.onItemClicked(mTvUserLogin.getText().toString()));
public void bindTo(GitHubUser user) {
mTvUserName.setText(user.name);
mTvUserLogin.setText(user.login);
mTvUserPage.setText(user.repos_url);
Picasso.with(mIvUserPicture.getContext())
.load(user.avatar_url)
.placeholder(R.drawable.ic_person_black_24dp)
.into(mIvUserPicture);
public static class GitHubUser {
public String avatar_
public String repos_
添加数据addUser, 其中notifyItemInserted通知更新.
可以自动生成Json解析类的网站.
首先创建`Retrofit“服务, 通过服务获取数据, 再依次分发给适配器.
* 用户获取类
* Created by wangchenlong on 15/12/31.
public class NetworkWrapper {
private static final String[] mFamousUsers =
{"SpikeKing", "JakeWharton", "rock3r", "Takhion", "dextorer", "Mariuxtheone"};
public static void getUsersInto(final UserListAdapter adapter) {
GitHubService gitHubService =
ServiceFactory.createServiceFrom(GitHubService.class, GitHubService.ENDPOINT);
Observable.from(mFamousUsers)
.flatMap(gitHubService::getUserData)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(adapter::addUser);
public static void getReposInfo(final String username, final RepoListAdapter adapter) {
GitHubService gitHubService =
ServiceFactory.createServiceFrom(GitHubService.class, GitHubService.ENDPOINT);
gitHubService.getRepoData(username)
.flatMap(Observable::from)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(adapter::addRepo);
网络请求无法在主线程上执行, 需要启动异步线程, 如Schedulers.newThread().
使用工厂模式ServiceFactory创建服务, 也可以单独创建服务.
创建Retrofit服务的工厂类.
* 工厂模式
* Created by wangchenlong on 15/12/31.
public class ServiceFactory {
public static &T& T createServiceFrom(final Class&T& serviceClass, String endpoint) {
Retrofit adapter = new Retrofit.Builder()
.baseUrl(endpoint)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
return adapter.create(serviceClass);
这是Retrofit 2.0的写法, 注意需要添加Rx和Gson的解析.
设置网络请求的Url.
* GitHub的服务
* Created by wangchenlong on 15/12/31.
public interface GitHubService {
String ENDPOINT = "";
@GET("/users/{user}")
Observable&UserListAdapter.GitHubUser& getUserData(@Path("user") String user);
@GET("/users/{user}/repos")
Observable&RepoListAdapter.GitHubRepo[]& getRepoData(@Path("user") String user);
详情页面与主页类似, 参考代码, 不做细说.
5. 线程安全
Rx的好处之一就是可以防止内存泄露, 即根据页面生命周期, 处理异步线程的结束. 可以使用RxLifecycle库处理生命周期.
Activity类继承RxAppCompatActivity, 替换AppCompatActivity.
启动一个循环线程.
* Rx的线程安全
* Created by wangchenlong on 15/12/31.
public class SafeActivity extends RxAppCompatActivity {
private static final String TAG = "DEBUG-WCL: " + SafeActivity.class.getSimpleName();
@Bind(R.id.simple_tv_text) TextView mTvT
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple);
ButterKnife.bind(this);
Observable.interval(1, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.compose(bindToLifecycle())
.subscribe(this::showTime);
private void showTime(Long time) {
mTvText.setText(String.valueOf("时间计数: " + time));
Log.d(TAG, "时间计数器: " + time);
protected void onPause() {
super.onPause();
Log.w(TAG, "页面关闭!");
继承RxAppCompatActivity, 添加bindToLifecycle方法管理生命周期. 当页面onPause时, 会自动结束循环线程. 如果注释这句代码, 则会导致内存泄露.
6. RxBinding
RxBinding是Rx中处理控件异步调用的方式, 也是由Square公司开发, Jake负责编写. 通过绑定组件, 异步获取事件, 并进行处理. 编码风格非常优雅.
除了RxJava, 再添加RxBinding的依赖.
compile 'com.jakewharton.rxbinding:rxbinding:0.3.0'
compile 'com.jakewharton.rxbinding:rxbinding-appcompat-v7:0.3.0'
compile 'com.jakewharton.rxbinding:rxbinding-design:0.3.0'
Toolbar和Fab, 两个较新的控件.
&?xml version="1.0" encoding="utf-8"?&
&android.support.design.widget.CoordinatorLayout
xmlns:android="/apk/res/android"
xmlns:tools="/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方法.
&?xml version="1.0" encoding="utf-8"?&
xmlns:android="/apk/res/android"
xmlns:app="/apk/res-auto"
xmlns:tools="/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"&
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/usual_approach"/&
android:id="@+id/rxbinding_et_usual_approach"
android:layout_width="match_parent"
android:layout_height="48dp"
android:hint="@null"/&
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/reactive_approach"/&
android:id="@+id/rxbinding_et_reactive_approach"
android:layout_width="match_parent"
android:layout_height="48dp"
android:hint="@null"/&
android:id="@+id/rxbinding_tv_show"
android:layout_width="match_parent"
android:layout_height="wrap_content"/&
使用ButterKnife注入控件, 使用RxBinding方式绑定控件, 异步监听事件.
* Created by wangchenlong on 16/1/25.
public class BindingActivity extends AppCompatActivity {
@Bind(R.id.rxbinding_t_toolbar) Toolbar mTT
@Bind(R.id.rxbinding_et_usual_approach) EditText mEtUsualA
@Bind(R.id.rxbinding_et_reactive_approach) EditText mEtReactiveA
@Bind(R.id.rxbinding_tv_show) TextView mTvS
@Bind(R.id.rxbinding_fab_fab) FloatingActionButton mFabF
@Override protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_binding);
ButterKnife.bind(this);
initToolbar();
initFabButton();
initEditText();
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);
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);
private void initFabButton() {
RxView.clicks(mFabFab).subscribe(this::onFabClicked);
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);
private void onSnackbarDismissed(int event) {
String text = "Snackbar消失代码:" +
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
private void initEditText() {
mEtUsualApproach.addTextChangedListener(new TextWatcher() {
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) {
RxTextView.textChanges(mEtReactiveApproach).subscribe(mTvShow::setText);
Toolbar使用RxToolbar监听点击事件; Snackbar使用RxSnackbar监听;
EditText使用RxTextView监听; 其余使用RxView监听.
OK, That’s all! Enjoy It!
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:23572次
排名:千里之外
转载:95篇
(1)(6)(11)(19)(60)(4)

我要回帖

更多关于 rxandroid jar包下载 的文章

 

随机推荐