适合的才是最好的-RxJava篇_海重山青的博客-程序员秘密

技术标签: Android  

对于程序猿来说,Demo是最好的起手

而对于RxJava来说,你可以简单理解成:

  • 是一个观察者模式框架
  • 替代AsyncTask成为更好的异步操作工具
  • 即便逻辑再复杂,对于RxJava来说就是:简洁

首先上Demo

public static void main(String[] args) {
    // 0.准备一些数据
    Integer[] numbers = { 1, 2, 3, 4 };
    List<Integer> lists = Arrays.asList(numbers);

    // 1.创建一个被观察者
    //      被观察者很明显从List集合获取数据,现在就等着有人来订阅~
    Observable<Integer> observable = Observable.from(lists);

    // 2.创建一个观察者
    //      SubScriber是Observer的实现类,所以也是一个观察者
    Observer<Integer> observer = new Observer<Integer>() {
        @Override
        public void onNext(Integer data) {
            // 被观察者发送的数据都会送到这里
            System.out.println("Rx -- onNext:" + data);
        }

        @Override
        public void onCompleted() {
            // 被观察者发送完数据会调用该方法
            System.out.println("Rx -- Complete!");
        }

        @Override
        public void onError(Throwable e) {
            // 被观察者传输数据中发生异常会调用该方法
            System.out.println("Rx -- Error!");
        }
    };

    // 3.订阅
    //      正常来说应该是:observer.subscribe(observable); 看起来更合乎逻辑
    //      这样反而像是:被观察者 订阅了 观察者(报纸 订阅了 读者)
    //      这涉及到流式编程,姑且先这样记住吧
    observable.subscribe(observer);
}

运行结果:

这里写图片描述

  • 在观察者订阅的顺间,被观察者就发送数据过来了
  • 数据发送过来调用的方法:onNext()
  • 数据发送完成调用的方法:onCompleted()
  • 数据发送期间出现异常调用的方法:onError()

不要看代码多了,但逻辑很简洁!只有逻辑上的简洁才是真正的简洁!

上面的Demo看完一遍,大概知道有什么样的角色在扮演。

现在分析下每个角色:

观察者

作用:接收数据并进行处理

观察者毫无疑问就是Observer,但它是接口。在实际操作中,一般都使用它的抽象实现类Subscriber。两者使用方式完全一样。

public abstract class Subscriber<T> implements Observer<T>, Subscription

现在来看看观察者常用的创建方式

第一种:new Observer()接口

Observer<Integer> observer = new Observer<Integer>(){
    @Override
    public void onCompleted() {
    }

    @Override
    public void onError(Throwable e) {
    }

    @Override
    public void onNext(Integer i) {
    }
};

第二种:new Subscriber()抽象类

Subscriber<Integer> subscriber = new Subscriber<Integer>(){
    @Override
    public void onCompleted() {
    }

    @Override
    public void onError(Throwable e) {
    }

    @Override
    public void onNext(Integer i) {
    }
};

Subscriber中有一个方法:

/**
 * This method is invoked when the Subscriber and Observable have been connected but the Observable has
 * not yet begun to emit items or send notifications to the Subscriber. Override this method to add any
 * useful initialization to your subscription, for instance to initiate backpressure.
 */
public void onStart() {
    // do nothing by default
}
  • 很明显是留给调用者自己重写
  • 英文好的可以自己看注释
  • 这里大致说下意思:这个方法是在观察者和被观察者已连接,但是被观察者还没有向观察者发送数据时进行调用
  • 所以,这个方法就是用来做初始化用的。

除此之外,Subscriber实现的Subscription接口还有两个方法:

public interface Subscription {
    
    void unsubscribe(); // 取消订阅
    boolean isUnsubscribed(); // 是否已经取消订阅
}
  • 取消订阅后,观察者将不会再接收事件
  • 取消之前先判断一下isUnsubscribed()

  • 如果程序中没有调用取消订阅方法,被观察者会始终持有观察者引用。造成内存泄漏

被观察者

作用:作为数据的发送方,它决定什么时候发送,怎么发送

被观察者ObservableJava里也有。很多地方都喜欢用这个单词作为被观察者,这也是它的直译。但是就因为都一样,所以小心不要导错包了。

现在来看看被观察者常用的创建方式

第一种:Observable.create()

Observable observable = Observable.create(new Observable.OnSubscribe<Integer>(){
    @Override
    public void call(Subscriber<? super Integer> subscriber) {

    }
});
  • create()方法接收一个OnSubscribe接口参数
  • OnSubscribeObservable的内部接口
public interface OnSubscribe<T> extends Action1<Subscriber<? super T>> {
    
    // cover for generics insanity
}
  • 根据接口名,顾名思义。当观察者被订阅的时候,会调用这个call()方法

  • 下面举个小例子:

public static void main(String[] args) {
    // 观察者
    Observer<Integer> observer = new Observer<Integer>(){
        @Override
        public void onCompleted() {
            System.out.println("接收数据结束");
        }
        @Override
        public void onError(Throwable e) {

        }
        @Override
        public void onNext(Integer t) {
            System.out.println("接收数据:" + t);
        }
    };
    // 被观察者
    Observable observable = Observable.create(new Observable.OnSubscribe<Integer>(){
        @Override
        public void call(Subscriber<? super Integer> subscriber) {
            subscriber.onNext(1);
            subscriber.onNext(2);
            subscriber.onNext(3);
            subscriber.onCompleted();
        }
    });

    // 订阅
    observable.subscribe(observer);
}

运行结果:

这里写图片描述

注意:

这个方法已经被废弃了,推荐使用SyncOnSubscribeAsyncOnSubscribe

看名字应该知道是什么意思

这里写图片描述

第二种:Observable.from()

Integer[] nums = {
   1, 2, 3};
Observable observable = Observable.from(nums);
  • 从一个数组Iterable中依次发送数据元素

第三种:Observable.just()

Observable observable = Observable.just(1, 2, 3);
  • 这个更直接。将参数依次发送过来。

订阅

observable.subscribe(observer);

其内部实现:

这里写图片描述

  • subscriber.onStart()就是观察者中内置的用于初始化的方法
  • 被观察者.call(subscriber)就是

这里写图片描述

  • 最后把观察者当成订阅者返回。前面说过
public abstract class Subscriber<T> implements Observer<T>, Subscription
  • 所以,你可以:
// 订阅
Subscription subscription = observable.subscribe(observer);
// 取消订阅
subscription.unsubscribe();
  • 形成链式编程

关于Action

前面在被观察者的第一种创建方式Observable.create()中,接收的参数是OnSubscribe接口。它继承了Action1

public interface OnSubscribe<T> extends Action1<Subscriber<? super T>> {
    
    // cover for generics insanity
}
  • 被观察者订阅时,OnSubscribecall()方法才会被调用
  • 这个call()就是Action1
public interface Action1<T> extends Action {
    
    void call(T t);
}

至于这个Action,你可以理解为就是一次单纯的行为,一个单纯的回调

有很多的Actionx

public interface Action0 extends Action {
    
    void call();
}

public interface Action1<T> extends Action {
    
    void call(T t);
}

public interface Action2<T1, T2> extends Action {
    
    void call(T1 t1, T2 t2);
}

public interface Action3<T1, T2, T3> extends Action {
    
    void call(T1 t1, T2 t2, T3 t3);
}
  • 0就代表call()方法没有参数
  • 1就代表call()方法有1个参数
  • 2就代表call()方法有2个参数

  • 至于ActionN接口

public interface ActionN extends Action {
    
    void call(Object... args);
}

Observable.subscribe(..)的时候,里面除了ObserverSubscriber这两个观察者之外。还可以接受一个Action

Action1<Integer> action1 = new Action1<Integer>() {
    @Override
    public void call(Integer num) {
        System.out.println("接收到数据:" + num);
    }
};
observable.subscribe(action1);

常用方法

map

People[] peoples = new People[]{
        new People("张三", 18, new String[]{
   "睡觉", "吃饭", "打豆豆"}),
        new People("李四", 19, new String[]{
   "编程", "泡妞", "LOL"})
};
// 观察者
Subscriber<String> subscriber = new Subscriber<String>() {
    @Override
    public void onNext(String name) {
        System.out.println("接收信息:" + name);
    }
    @Override
    public void onCompleted() {
    }
    @Override
    public void onError(Throwable e) {
    }
};
// 被观察者
Observable.from(peoples).map(new Func1<People, String>() {
        @Override
        public String call(People people) {
            return people.getName();
        }
    }).subscribe(subscriber);
  • 可以看到被观察者从People数组里读取每一个元素
  • map方法里找到每一个元素对象的name传递给观察者
  • 观察者接收并使用
  • 这里转换范围很大,不仅仅只是提取属性。

运行结果

这里写图片描述

flatMap

People[] peoples = new People[]{
        new People("张三", 18, new String[]{
   "睡觉", "吃饭", "打豆豆"}),
        new People("李四", 19, new String[]{
   "编程", "泡妞", "LOL"})
};
// 观察者
Subscriber<String> subscriber = new Subscriber<String>() {
    @Override
    public void onNext(String hobby) {
        System.out.println("接收信息:" + hobby);
    }
    @Override
    public void onCompleted() {
    }
    @Override
    public void onError(Throwable e) {
    }
};
// 被观察者
Observable.from(peoples).flatMap(new Func1<People, Observable<String>>() {
        @Override
        public Observable<String> call(People people) {
            return Observable.from(people.getHobby());
        }
    }).subscribe(subscriber);
  • 效果和map是类似的
  • 区别在于map是用于一对一,而flatMap是用于一对多
  • 被观察者从People数组读取每一个对象,call()里读取每一个对象的hobby属性,并依次返回其中的一个元素

运行结果

这里写图片描述

filter

People[] peoples = new People[]{
        new People("张三", 18, new String[]{
   "睡觉", "吃饭", "打豆豆"}),
        new People("李四", 19, new String[]{
   "编程", "泡妞", "LOL"})
};
// 观察者
Subscriber<String> subscriber = new Subscriber<String>() {
    @Override
    public void onNext(String name) {
        System.out.println("接收信息:" + name);
    }
    @Override
    public void onCompleted() {
    }
    @Override
    public void onError(Throwable e) {
    }
};
// 被观察者
Observable.from(peoples).filter(new Func1<People, Boolean>() {

    @Override
    public Boolean call(People t) {
        return t.getAge() > 18;
    }
}).map(new Func1<People, String>() {
    @Override
    public String call(People people) {
        return people.getName();
    }
}).subscribe(subscriber);

运行结果

这里写图片描述

线程

RxJava遵循的线程原则在那个线程订阅,则被观察者和观察者的操作都在该线程

通过Schedulers切换线程

  • Schedulers.immediate()默认值。在当前线程运行。
  • AndroidSchedulers.mainThread():在Android主线程运行。
    • 注意:这个是RxAndroid里的。必须要导入RxAndroidjar包。RxJava里是没有的。
  • Schedulers.newThread()总是开启新线程运行。
  • Schedulers.io():如果操作涉及到I/O使用该项。

    • 也是总是开启新线程运行
    • 内部有线程池和复用
  • Schedulers.computation():如果操作涉及到图形计算等使用该项。

还是之前例子,但是增加两行代码:

People[] peoples = new People[]{
        new People("张三", 18, new String[]{
   "睡觉", "吃饭", "打豆豆"}),
        new People("李四", 19, new String[]{
   "编程", "泡妞", "LOL"})
};
// 观察者
Subscriber<String> subscriber = new Subscriber<String>() {
    @Override
    public void onNext(String name) {
        System.out.println("接收信息:" + name);
    }
    @Override
    public void onCompleted() {
    }
    @Override
    public void onError(Throwable e) {
    }
};
// 被观察者
Observable.from(peoples).filter(new Func1<People, Boolean>() {

    @Override
    public Boolean call(People t) {
        return t.getAge() > 18;
    }
}).map(new Func1<People, String>() {
    @Override
    public String call(People people) {
        return people.getName();
    }
}).subscribeOn(Schedulers.immediate()) // 当前线程
.observeOn(Schedulers.io()) // io线程
.subscribe(subscriber);
  • 被观察者在新开起的IO线程读取/过滤/转换操作
  • 数据传给观察者
  • 观察者当前线程显示数据

运行结果

这里写图片描述

总结

  • RxJava确实是一个非常强大的流式编程工具
  • 再复杂的逻辑,RxJava都能很简洁的表示
  • 一句代码完成线程切换,很方便
  • 用多了才知道它的美~
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ChongXue91/article/details/79153558

智能推荐

Zabbix-架构与部署_CN-FuWei的博客-程序员资料_zabbix架构

一、zabbix结构组成zabbix软件结构组成:1.Zabbix Web GUI: 提供Web界面2.Zabbix Database:提供数据存储功能,专用于存储配置信息,以及采集到的数据3.Zabbix Server: 接收Agent采集数据的核心组件。4.Zabbix Agent: 部署在被监控主机上,用于采集本地数据。5.Zabbix Proxy: 当被监控节点较多时,用于减轻Server压力的组件,也用于分布式监控系统。由Proxy接收数据后统一发送至Server。二、

cisco交换机Telnet配置_weixin_34357436的博客-程序员资料

cisco交换机Telnet配置 switch&gt;en ;第一次密码为空switch#conf t ;进入全局配置模式switch(config)#hostname swa ;设置交换机名swa(config)...

MacOs M1芯片iTerm安装lrzsz_不想上班只想摸鱼的程序员的博客-程序员资料

首先是iterm的下载和lrzsz的安装,这类文章很多,附上一个自认为比较全面的MAC iTerm2 下 使用 lszrz_lightWay的博客-程序员资料_lszrzMAC iTerm2 下 使用 lszrzMAC iTerm2 下 使用 lszrz需要什么什么是 lrzsz为什么需要lszrz具体过程安装lrzsz下载iterm2-zmodem移动到指定位置并赋予可执行权限给iTerm2添加触发器需要什么homebrew包管理工具iTerm2终端命令行wget命令行工具什么是 lrzsz Lrz

Robot Framework学习(8):Web自动化测试_csdn怀的博客-程序员资料

web自动化测试用到的库是Selenium2Library与浏览器相关的关键字1. Open Browser    https://www.baidu.com  ff/chrome    # 打开浏览器注:要想通过不同的浏览打开URL地址,一定要安装浏览器相对应的驱动2. Close Browser        # 关闭浏览器3. Close All Browser   ...

超硬核Java学习路线图+学习资源+实战项目汇总,看完以后不用再问我怎么学Java了!_程序员书单的博客-程序员资料

​之前写过很多次关于Java学习指南、Java技术路线图的文章。但是总还是有小伙伴来问我,Java怎么学,项目怎么做,资源怎么找,真是让人头秃。于是这次黄小斜决定来一波狠的,把所有这些内容都整理起来,做成一份非常硬核的Java学习指南+路线图,一篇文章搞定Java学习,360度无死角(可能)如果你们喜欢这类硬核的文章,以后我也会继续这么硬核下去的!不要忘了分享噢。以下就是本文的主要内容,万字长文,你可悠着点看,拒绝到收藏夹吃灰!一、Java学习路线图1 计算机基础**2**Java.

随便推点

linux命令---netstat_二两酒馆的博客-程序员资料

概述Netstat 是一款命令行工具,用于显示各种网络相关信息,可用于列出系统上所有的网络套接字连接情况,包括 tcp, udp 以及 unix 套接字,另外它还能列出处于监听状态(即等待接入请求)的套接字应用命令格式根据man手册有很多参数(截图了偷个懒) 参数说明介绍一下常用参数(同样偷懒一下下) Options Details -a 等价参数:- -all,显示所有选项,包括监

背包 DP 背包_melo melo的博客-程序员资料_背包dp

背包 题目 是dp中较为常见的题目分为 0--1 背包 ,完全背包 和多重背包这三类 是越来越深入的首先来介绍一下 0--1背包 ; 首先 0 --1 背包的含义是 给你一个容量位M的背包 然后给你n个物品 ,每个物品具有一定价值和一定重量 会站一定的背包空间答案是在n个物品中那几个 然后使得到的价值最大 首先0 --1入门 首先...

单文件程序库2_yazhouren的博客-程序员资料

Packageshtmk edited this page 5 days ago · 253 revisions Pages 3HomeExplanation of package.jsonPackagesClone this wiki locally Clone in DesktopLis

Android学习——控件ListView的使用_anjiukonghe77852的博客-程序员资料

一、ListView的简单用法首先新建一个ListViewTest项目,并让Android Studio自动创建好活动。然后修改activity_main.xml中的代码,如下: 1 &lt;?xml version="1.0" encoding="utf-8"?&gt; 2 &lt;LinearLayout xmlns:android="http://schemas.a...

ABAP ALV显示简单例子_土星环的土的博客-程序员资料_abap alv 例子

*&amp;---------------------------------------------------------------------**&amp;ReportZ_210113_02*&amp;---------------------------------------------------------------------**&amp;*&amp;---------------------------------------------------------------..

推荐文章

热门文章

相关标签