`
hzy3774
  • 浏览: 992357 次
  • 性别: Icon_minigender_1
  • 来自: 珠海
社区版块
存档分类
最新评论

RxJava在Android中使用笔记

 
阅读更多

使用RxJava可以方便实现观察者模式,数据转换和线程之间通信

https://github.com/ReactiveX/RxJava

在Android中使用RxAndroid增加安卓主线程支持:

https://github.com/ReactiveX/RxAndroid

实际开发中在gradle中注册对应的依赖即可:

compile 'io.reactivex:rxandroid:1.1.0'

 观察者模式一般要有两个对象:

1.被观察者:Obserable

2.观察者:Observer

观察者和被观察者绑定后,被观察者在某种事件发生时会向所有观察它的观察者发送事件,即调用观察者的回调函数。

 

使用java.util里的观察者应该是这样的:

 

import android.util.Log;

import java.util.Observable;
import java.util.Observer;

public class ObserverTest {

    void test0() {
        //创建被观察者
        DemoObserable obserable = new DemoObserable();
        //创建一个观察者
        Observer observer1 = new Observer() {
            //观察者接收到事件时的操作
            @Override
            public void update(Observable observable, Object data) {
                Log.e("TAG", "ToObserver1: " + data);
            }
        };
        //添加绑定
        obserable.addObserver(observer1);
        //被观察者发送事件
        obserable.subscribe("Hello World!!");
        //被观察者将观察者移除
        obserable.deleteObserver(observer1);
    }

    //被监听者
    public class DemoObserable extends Observable {

        //被监听者发送数据给所有观察者
        void subscribe(String data) {
            setChanged();
            notifyObservers(data);
        }

    }
}

 假设观察者有多个,可以依次注册,删除:

 

//创建被观察者
        DemoObserable obserable = new DemoObserable();
        //创建一个观察者
        Observer observer1 = new Observer() {
            //观察者接收到事件时的操作
            @Override
            public void update(Observable observable, Object data) {
                Log.e("TAG", "ToObserver1: " + data);
            }
        };
        //创建一个观察者
        Observer observer2 = new Observer() {
            //观察者接收到事件时的操作
            @Override
            public void update(Observable observable, Object data) {
                Log.e("TAG", "ToObserver2: " + data);
            }
        };
        //添加绑定
        obserable.addObserver(observer1);
        obserable.addObserver(observer2);
然而,我们接下来使用 rx.Observer, rx.Observable, 思想也是类似的:
1.观察者与被观察者
void test0() {

        Observable.OnSubscribe<String> onSubscribe = new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                subscriber.onNext("hello world!!");
                subscriber.onCompleted();
            }
        };

        Observable<String> observable = Observable.create(onSubscribe);

        Observer<String> observer = new Observer<String>() {
            @Override
            public void onNext(String s) {
                Log.e("TAG", s);
            }

            @Override
            public void onCompleted() {
                Log.e("TAG", "completed");
            }

            @Override
            public void onError(Throwable e) {
                Log.e("TAG", "error" + e);
            }
        };

        observable.subscribe(observer);

    }
 完成了类似的功能。
Observable构造方法是保护的,只能通过提供的静态方法创建对象,如Observable.create()
RxJava可以使用链式调用简化代码,所以也可以写成:
Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                subscriber.onNext("hello world!!");
                subscriber.onCompleted();
            }
        }).subscribe(new Observer<String>() {
            @Override
            public void onNext(String s) {
                Log.e("TAG", s);
            }

            @Override
            public void onCompleted() {
                Log.e("TAG", "completed");
            }

            @Override
            public void onError(Throwable e) {
                Log.e("TAG", "error" + e);
            }
        });
 如果直接知道被监听者发送事件onNext()时的参数,可以使用just()来创建Observable,效果和上例一样
Observable.just("Hello World!")
                .subscribe(new Observer<String>() {
                    @Override
                    public void onCompleted() {
                        Log.e("TAG", "complete");
                    }
                    @Override
                    public void onError(Throwable e) {

                    }
                    @Override
                    public void onNext(String s) {
                        Log.e("TAG", s);
                    }
                });
 just函数可以传入多个参数,事件依次调用后最后执行onComplete()
Observable.just("Hello World!", "RxJava Demo")
                .subscribe(new Observer<String>() {
                    @Override
                    public void onCompleted() {
                        Log.e("TAG", "complete");
                    }
                    @Override
                    public void onError(Throwable e) {

                    }
                    @Override
                    public void onNext(String s) {
                        Log.e("TAG", s);
                    }
                });
 如果观察者只需要重写onNext()方法,可以直接用ActionX来节省掉onError和onComplete的代码:
Observable.just("Hello World!", "RxJava Demo")
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        Log.e("TAG", s);
                    }
                });
 现在观察者也变的好简单,使用多个参数just()来创建也可以用from(T[])来创建,与上例等价:
String[] arr = {"Hello World!", "RxJava Demo"};
        Observable.from(arr)
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        Log.e("TAG", s);
                    }
                });
 如果不想用Observer,又想处理onError和onComplete,就需要在subscribe()函数传多个ActionX:
String[] arr = {"Hello World!", "RxJava Demo"};
        Action1 nextAction, errorAction;
        Action0 completeAction;
        nextAction = new Action1<String>() {
            @Override
            public void call(String s) {
                Log.e("TAG", s);
            }
        };
        errorAction = new Action1<Exception>() {
            @Override
            public void call(Exception e) {
                e.printStackTrace();
            }
        };
        completeAction = new Action0() {
            @Override
            public void call() {
                Log.e("TAG", "complete");
            }
        };
        Observable.from(arr)
                .subscribe(nextAction, errorAction, completeAction);
 2.观察者与被观察者在不同线程
加上线程控制语句subscribeOn,observeOn,就可以将被观察者和观察者指定在不同线程中:
Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                Log.e("TAG", "I am in computation");
                subscriber.onNext("Hello World!!");
            }
        })
                .subscribeOn(Schedulers.computation())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        Log.e("TAG", s);
                    }
                });
 两个操作发生在不同线程中,通过log可以看出来:
03-29 21:00:39.333 13153-13226/com.hzy.rxjavademo E/TAG: I am in computation
03-29 21:00:39.334 13153-13153/com.hzy.rxjavademo E/TAG: Hello World!!
03-29 21:00:39.914 13153-13227/com.hzy.rxjavademo E/TAG: I am in computation
03-29 21:00:39.915 13153-13153/com.hzy.rxjavademo E/TAG: Hello World!!
03-29 21:00:40.607 13153-13228/com.hzy.rxjavademo E/TAG: I am in computation
03-29 21:00:40.608 13153-13153/com.hzy.rxjavademo E/TAG: Hello World!!
 通过日志pid可以看到,Observable执行会开启新的线程,而Observer观察者收到消息后执行的操作在UI线程执行,所以可以方便的替代之前Android的new Thread加Handler发送消息的机制。
如下代码就可以完成一个完整的异步网络请求,并把结果和出错信息通知到UI线程的观察者:
Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                try {
                    URL url = new URL("https://m.baidu.com/");
                    InputStream is = url.openStream();
                    InputStreamReader isr = new InputStreamReader(is);
                    BufferedReader br = new BufferedReader(isr);
                    String line;
                    StringBuilder builder = new StringBuilder();
                    while ((line = br.readLine()) != null) {
                        builder.append(line);
                    }
                    subscriber.onNext(builder.toString());
                } catch (Exception e) {
                    subscriber.onError(e);
                }
            }
        })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        Log.e("TAG", s);
                    }
                }, new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                        throwable.printStackTrace();
                    }
                });
 异步操作变得好简单,而且很容易理解
3.数据的过滤
数据过滤使用filter方法:
String[] arr = {"Hello World!", "RxJava Demo", "RxAndroid"};
        Observable.from(arr)
                .filter(new Func1<String, Boolean>() {
                    @Override
                    public Boolean call(String s) {
                        return s.startsWith("Rx");
                    }
                })
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        Log.e("TAG", s);
                    }
                });
 这时,如例子中所有返回以Rx开头字符串的事件,才会去通知观察者。
4.数据的转换
消息发送者返回的数据用map()进行转化后再发送给观察者
Observable.just(123)
                .map(new Func1<Integer, String>() {
                    @Override
                    public String call(Integer integer) {
                        String ret = integer + ":" + integer * 2;
                        return ret;
                    }
                }).subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                Log.e("TAG", s);
            }
        });
 把消息发送者发来的 Integer类型转成String类型再传给观察者去处理。
使用lift()把一个观察者转成另一个:
Observable.just(123)
                .lift(new Observable.Operator<String, Integer>() {
                    @Override
                    public Subscriber<? super Integer> call(final Subscriber<? super String> subscriber) {
                        return new Subscriber<Integer>() {
                            @Override
                            public void onCompleted() {
                                subscriber.onCompleted();
                            }
                            @Override
                            public void onError(Throwable e) {
                                subscriber.onError(e);
                            }
                            @Override
                            public void onNext(Integer integer) {
                                subscriber.onNext("hello" + integer);
                            }
                        };
                    }
                }).subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                Log.e("TAG", s);
            }
        });
 把一个Integer类型的Subscriber转成String类型,Subscriber实现Observer接口,所以Subscriber也是观察者。

使用compose直接把被监听者转换掉,Transformer规定了转换的规则,Obserable怎么转换呢,还是用个map来转吧,Transformer在此显得多此一举了:

Observable.just(123)
                .compose(new Observable.Transformer<Integer, String>() {
                    @Override
                    public Observable<String> call(Observable<Integer> integerObservable) {
                        return integerObservable.map(new Func1<Integer, String>() {
                            @Override
                            public String call(Integer integer) {
                                return integer + "hello";
                            }
                        });
                    }
                }).subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                Log.e("TAG", s);
            }
        });

 把Integer类型转换成String类型

 

5.条件判断

条件判断的Observable范型都会被转换成Boolean类型

判断是否存在某种类型用exists()函数

Observable.just(123, 20, 34, 4, 0, 2)
                .exists(new Func1<Integer, Boolean>() {
                    @Override
                    public Boolean call(Integer integer) {
                        return integer == 0;
                    }
                })
                .subscribe(new Action1<Boolean>() {
                    @Override
                    public void call(Boolean aBoolean) {
                        Log.e("TAG", "" + aBoolean);
                    }
                });

判断那些值中是否存在为0的Integer,显然存在,返回true

用all()判断是否全都是某种情况:

Observable.just(123, 20, 34, 4, 0, 2)
                .all(new Func1<Integer, Boolean>() {
                    @Override
                    public Boolean call(Integer integer) {
                        return integer > 0;
                    }
                })
                .subscribe(new Action1<Boolean>() {
                    @Override
                    public void call(Boolean aBoolean) {
                        Log.e("TAG", "" + aBoolean);
                    }
                });

上面那些值全都大于0么,显然不是,返回false。

 

6.观察者嵌套

有一种场景,观察者收到消息后,不能完全处理掉消息,自身又作为消息发送者给其他观察者发消息。

Observable.just(123)
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer integer) {
                        Observable.just(integer)
                                .subscribe(new Action1<Integer>() {
                                    @Override
                                    public void call(Integer integer) {
                                        Log.e("TAG", "" + integer);
                                    }
                                });
                    }
                });

 两层嵌套之后缩进已经很长了,为解决这个问题,可以用flatMap()来减少缩进:

Observable.just(123)
                .flatMap(new Func1<Integer, Observable<Integer>>() {
                    @Override
                    public Observable<Integer> call(Integer integer) {
                        return Observable.just(integer);
                    }
                }).subscribe(new Action1<Integer>() {
            @Override
            public void call(Integer integer) {
                Log.e("TAG", "" + integer);
            }
        });

 这样,缩进好多了。

最后是一个综合实例:
//使用IO线程读取SD卡上所有png文件并在主线程上打印
    private void testy() {
        Observable.create(new Observable.OnSubscribe<File>() {
            @Override
            public void call(Subscriber<? super File> subscriber) {
                //获取外部存储上的所有文件
                File exDir = Environment.getExternalStorageDirectory();
                traceFiles(exDir, subscriber);
            }
        }).subscribeOn(Schedulers.io())
                //过滤出png文件
                .filter(new Func1<File, Boolean>() {
                    @Override
                    public Boolean call(File file) {
                        return file.isFile() && file.getName().endsWith(".png");
                    }
                    //使用buffer防止消息发送过快
                }).onBackpressureBuffer()
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<File>() {
                    @Override
                    public void call(File file) {
                        Log.e("TAG", file.getAbsolutePath());
                    }
                }, new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                        Log.e("TAG", "Error:" + throwable);
                        throwable.printStackTrace();
                    }
                });
    }

    private void traceFiles(File file, Subscriber<? super File> subscriber) {
        subscriber.onNext(file);
        if (file.isDirectory()) {
            for (File f : file.listFiles()) {
                traceFiles(f, subscriber);
            }
        }
    }
  
结束
分享到:
评论

相关推荐

    RxJava&RxAndroid;笔记

    RxJava与RxAndroid通常结合使用,开发者可以利用RxJava的响应式特性,在Android应用中处理复杂的数据流和异步任务,使得代码更加简洁易读,并且提升应用的性能和响应速度。同时,通过利用RxAndroid提供的特定于...

    Android-一个利用RxJava在TextView和EditText上渲染的markdown解析器

    通过研究和理解这些代码,开发者不仅可以学习如何实现Markdown解析,还能深入了解如何在Android应用中有效地使用RxJava。这对于提升Android开发技能,尤其是处理文本和事件流的处理,有着极大的帮助。

    读书笔记:Android中的响应式编程RxJavaRxAndroid.zip

    读书笔记:Android中的响应式编程RxJavaRxAndroid

    android 非常全培训笔记

    在Android开发领域,掌握全面的知识点对于从培训到工作至关重要。这份"android 非常全培训笔记"无疑是为开发者提供了一个宝贵的参考...建议读者结合笔记中的实例逐步学习,不断练习,从而在Android开发之路上越走越远。

    Android--极简笔记App

    在移动设备上,笔记应用是不可或缺的一部分,而“Android--极简笔记App”正是这样一个基于Material Design设计规范的轻量级应用程序。这款应用利用了Android平台上的先进技术和最佳实践,如RxAndroid、MVP(Model-...

    android 学习笔记(全全整理)

    8. **权限管理**:Android 6.0(API级别23)以后的动态权限申请,理解运行时权限模型,以及在代码中如何处理权限请求。 9. **通知与服务**:创建和管理通知,使用Foreground Service确保服务在后台持续运行,以及...

    超全android 教程 笔记

    13. **多线程和异步处理**:Android中的UI线程不能执行耗时操作,因此需要使用线程池、AsyncTask、Handler或第三方库如RxJava来处理后台任务。 14. **动画(Animation)**:Android支持属性动画、帧动画和视图动画,...

    新版Android开发教程及笔记-完整版

    新版Android开发教程及笔记将涵盖Android系统的基本架构、应用程序生命周期管理以及UI设计等核心概念。 1. **Android系统架构**:Android系统分为应用层、应用框架层、系统运行库层和Linux内核层。开发者主要在应用...

    Android学习入门笔记.zip

    Android学习入门笔记主要涵盖了一系列关于Android开发的基础知识,旨在帮助初学者快速掌握这一全球最流行的移动操作系统...通过阅读“Android学习入门笔记”中的学习课件,你应该能逐步建立起对Android开发的全面认知。

    Android开发教程笔记完全版.zip

    10. **第三方库集成**:许多第三方库如Retrofit、Dagger、RxJava等,大大简化了Android开发,笔记会讲解如何选择并正确地集成这些库。 11. **单元测试与自动化测试**:理解JUnit、Espresso等工具,进行应用的功能...

    Android代码-一个集Gank.Io,Rxjava示例,操作符,MD控件使用,各种好玩Ap示例的学习App。

    Rxjava操作符,中文文档,使用案例,方便随时查阅学习. 安卓艺术开发探索读书笔记,EffectiveJava读书笔记. 收集各大神博客以及安卓笔记,安卓面试笔记等方便手机端查看. 更新说明 v2.2.2 1.增加了一些最近在学习比较好...

    Android-MaterialDesign风格的开源照片笔记

    综上所述,这个开源项目展示了如何在Android应用中应用Material Design,使用MVP、Dagger2和RxJava等现代开发工具和框架,以及如何解决大型应用的Dex管理和加载问题,为开发者提供了学习和借鉴的价值。通过研究和...

    Android笔记本APP源码.zip

    3. **Android笔记应用的基本结构** - **MainActivity**: 应用的主要入口,通常负责初始化界面和处理用户交互。 - **NoteActivity/EditorActivity**: 用于创建和编辑笔记的活动,可能包括输入框、编辑器和保存功能...

    rxjava学习代码

    在IT行业中,RxJava是一个非常重要的库,尤其在Android开发中被广泛应用。它是一个响应式编程库,允许开发者以一种声明式的方式处理异步数据流。这个“rxjava学习代码”压缩包提供了一种深入理解RxJava 2.x版本的...

    Android笔记.zip

    在Android开发领域,掌握核心...以上只是Android开发中的冰山一角,这份"Android笔记"可能会涵盖更多细节和实战案例,是学习和进阶Android开发的宝贵资料。通过深入学习和实践,你可以成为一名出色的Android开发者。

    Android开发教程&笔记

    这个压缩包中的"Android开发教程&笔记"很可能包含了关于这些主题的详细资料,对于初学者或者经验丰富的开发者来说,都是宝贵的资源。 1. **Android基础知识**:Android是Google主导的开源移动操作系统,它基于Linux...

    Android开发教程笔记完全版毕业设计—(包含完整源码可运行).zip

    3. **Activity与Intent**:Activity是Android应用中的一个独立屏幕,Intent则用来在不同的Activity之间进行通信。理解Activity的生命周期和Intent的工作原理对于创建交互式应用至关重要。 4. **Fragment**:...

    AndroidNote, Android 进阶笔记,包含常用的技术框架、博客社区、书籍等。.zip

    《Android进阶笔记》是针对Android开发者的一份详尽学习资料,主要涵盖了各种技术框架、博客社区和推荐书籍,旨在帮助开发者深入理解Android系统并提升专业技能。这份资源的开源特性意味着开发者可以自由访问和分享...

    Android学习笔记

    以下将详细解析笔记中可能涉及的关键知识点。 1. **Android系统架构**:Android系统由Linux内核、运行库层、应用程序框架层以及应用程序层构成。理解这四层架构对开发者至关重要,它帮助我们了解系统如何工作,以及...

Global site tag (gtag.js) - Google Analytics