【Android】RxJava

1,概述

响应式编程,与java.Stream和kotlin流式编程异曲同工,不过提供了更强大功能,如线程切换。

android项目导入依赖:

// https://mvnrepository.com/artifact/io.reactivex/rxandroid
implementation group: 'io.reactivex', name: 'rxandroid', version: '1.2.1'

2,实例


public class RxJavaActivity extends AppCompatActivity {

    private static final String TAG = "RxJavaActivity";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rx_java);

        Observable.create(new Observable.OnSubscribe<List>() {
            @Override
            public void call(Subscriber<? super List> subscriber) {
                //从数据库取出资源,在io线程
                Log.d(TAG, "call:" + Thread.currentThread().getName());
                subscriber.onNext(List.of(1, 2, 3, 4, 5));
            }
        }).filter(new Func1<List, Boolean>() {
            @Override
            public Boolean call(List list) {
                return !list.isEmpty();
            }
        }).flatMap(new Func1<List, Observable<Integer>>() {
                @Override
                public Observable<Integer> call(List list) {
                    //计算线程
                    Schedulers.computation().createWorker().schedule(new Action0() {
                        @Override
                        public void call() {
                            for (int i = 0; i < list.size(); i++) {
                                Log.d(TAG, "computation : " + Thread.currentThread().getName() + " |" + list.get(i));
                            }
                        }
                    });
                    return Observable.from(list);
                }
            })
            .subscribeOn(Schedulers.io())// io线程拿数据
            .observeOn(AndroidSchedulers.mainThread())//主线程执行数据
            .subscribe(new Observer<Integer>() {
                @Override
                public void onCompleted() {
                    //onNext执行完毕后,回调此方法
                    Log.d(TAG, "onCompleted");
                }

                @Override
                public void onError(Throwable e) {
                    //处理异常
                }

                @Override
                public void onNext(Integer integer) {
                    //处理序列单个元素
                    Log.d(TAG, "onNext:" + Thread.currentThread().getName() + " |" + integer);
                }
            });
    }
}

3,关键代码解释

在不指定线程的情况下, RxJava 遵循的是线程不变的原则,即:在哪个线程调用 subscribe(),就在哪个线程生产事件;在哪个线程生产事件,就在哪个线程消费事件。如果需要切换线程,就需要用到 Scheduler (调度器)。

RxJava 已经内置了几个 Scheduler :

  • Schedulers.newThread(): 总是启用新线程,并在新线程执行操作。

  • Schedulers.io(): I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的 Scheduler。行为模式和 newThread() 差不多,区别在于 io() 的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下 io() 比 newThread() 更有效率。不要把计算工作放在 io() 中,可以避免创建不必要的线程。

  • Schedulers.computation(): 计算所使用的 Scheduler。这个计算指的是 CPU 密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算。这个 Scheduler 使用的固定的线程池,大小为 CPU 核数。不要把 I/O 操作放在 computation() 中,否则 I/O 操作的等待时间会浪费 CPU。

  • AndroidSchedulers.mainThread(),它指定的操作将在 Android 主线程运行

有了这几个 Scheduler ,就可以使用 subscribeOn() 和 observeOn() 两个方法来对线程进行控制了。

  • subscribeOn(): 指定 subscribe() 所发生的线程,即 Observable.OnSubscribe 被激活时所处的线程。或者叫做事件产生的线程。

  • observeOn(): 指定 Subscriber 所运行在的线程。或者叫做事件消费的线程。

4,线程切换实例

        Observable.defer(new Func0<Observable<String>>() {
            @Override
            public Observable<String> call() {
                Log.d(TAG, "Observable call :"+Thread.currentThread().getName());
                return Observable.just("task start!");
            }
        }).observeOn(Schedulers.io()) // 切换io线程
          .flatMap(new Func1<String, Observable<?>>() {
              @Override
              public Observable<?> call(String s) {
                  Log.d(TAG, "flatMap1 :"+Thread.currentThread().getName());
                  return Observable.just(s);
              }
          }).observeOn(Schedulers.computation()) // 切换计算线程
            .flatMap(new Func1<Object, Observable<?>>() {

                @Override
                public Observable<?> call(Object o) {
                    Log.d(TAG, "flatMap2 :"+Thread.currentThread().getName());
                    return Observable.just(o);
                }
            }).observeOn(AndroidSchedulers.mainThread())  //切换主线程
              .flatMap(new Func1<Object, Observable<?>>() {
                   @Override
                   public Observable<?> call(Object o) {
                       Log.d(TAG, "flatMap3 :"+Thread.currentThread().getName());
                       return Observable.just(o);
                   }
               })
               .subscribe(new Observer<Object>() {
                   @Override
                   public void onCompleted() {
                       Log.d(TAG, "onCompleted :"+Thread.currentThread().getName());

                   }

                   @Override
                   public void onError(Throwable e) {
                       Log.d(TAG, "onError :"+Thread.currentThread().getName());
                   }

                   @Override
                   public void onNext(Object o) {
                       Log.d(TAG, "onNext :"+Thread.currentThread().getName());
                   }
               });

日志

2021-12-27 13:13:20.682 29174-29174/com.zjw.demoApp D/RxJavaActivity: Observable call :main
2021-12-27 13:13:20.684 29174-32131/com.zjw.demoApp D/RxJavaActivity: flatMap1 :RxIoScheduler-2
2021-12-27 13:13:20.685 29174-32130/com.zjw.demoApp D/RxJavaActivity: flatMap2 :RxComputationScheduler-1
2021-12-27 13:13:20.874 29174-29174/com.zjw.demoApp D/RxJavaActivity: flatMap3 :main
2021-12-27 13:13:20.874 29174-29174/com.zjw.demoApp D/RxJavaActivity: onNext :main
2021-12-27 13:13:20.874 29174-29174/com.zjw.demoApp D/RxJavaActivity: onCompleted :main

进阶一


    public static void main(String[] args) {
        /*RxJava 默认同步流*/
        Observable.create(subscriber -> {
            subscriber.onNext("hello world!");
            subscriber.onCompleted();
        }).subscribe(o -> System.out.println(o + "| " + Thread.currentThread().getName()));

        printLines();

        /*许多操作符默认同步的,例如map*/
        Observable.create(subscriber -> {
            subscriber.onNext(1);
            subscriber.onNext(2);
            subscriber.onNext(3);
            subscriber.onCompleted();
        }).map((Func1<Object, Object>) o -> {
            System.out.println("map |" + getThreadName());
            return "Number" + o;
        }).subscribe(o -> System.out.println(o + "| " + Thread.currentThread().getName()));


        printLines();

        /*组合,实现RxJava并发*/
        final Observable<Object> a = Observable.create(s -> {
            new Thread(() -> {
                s.onNext(1);
                s.onNext(2);
                s.onNext(3);
            });
        });

        final Observable<Object> b = Observable.create(s -> {
            new Thread(() -> {
                s.onNext(4);
                s.onNext(5);
                s.onNext(6);
            });
        });

        final Observable<Object> c = Observable.merge(a, b);
        c.subscribe(System.out::println);

        printLines();

        /*数据是生产者推送式、而非消费者拉取式,好处是不用等待大容量数据生产完毕后去主动拉取*/
        Observable.create(s -> {
            for (int i = 0; i < 100; i++) {
                s.onNext(i);
            }
        }).skip(10) // 跳过前十个
                .take(5)  // 拿取5个
                .map((Func1<Object, Object>) o -> o + "_map")
                .subscribe(System.out::println);

        printLines();


        /*单值表达*/
        Single.create(s -> {
            s.onSuccess(1);
        }).mergeWith(Single.create(s -> {
            s.onSuccess(2);
        })).subscribe(System.out::println);

        printLines();

        //无返回值,只表达执行成功或失败
        Completable.create(s -> {
            System.out.println(getThreadName());
            s.onCompleted();
        }).subscribe();

        printLines();

        /* 一对多订阅模式*/
        // 生产者
        final Observable<Object> objectObservable = Observable.create(s -> {
            //主动检查是否取消订阅,避免不必要推送
            if (!s.isUnsubscribed())s.onNext(0);
            if (!s.isUnsubscribed())s.onNext(1);
            if (!s.isUnsubscribed())s.onNext(2);
        }).observeOn(Schedulers.io())
                .subscribeOn(Schedulers.newThread());

        // 消费者1
        final Subscription subscribe1 = objectObservable.subscribe(s -> {
            System.out.println(s + "_subscribe1 " + getThreadName());
        });

        // 消费者2
        final Subscription subscribe2 = objectObservable.subscribe(new Subscriber<Object>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable throwable) {

            }

            @Override
            public void onNext(Object o) {
                System.out.println(o + "_subscribe2 " + getThreadName());
                unsubscribe();
            }
        });

        //取消订阅
        subscribe1.unsubscribe();

        printLines();

        /*创建模式*/
        //单值发布
        Observable.just(0).subscribe(System.out::println);
        //容器发布
        Observable.from(List.of(1, 2, 3)).subscribe(System.out::println);
        //空值发布
        Observable.empty().subscribe(System.out::println);
        //错误发布
        Observable.error(new Throwable("test")).subscribe(new Observer<Object>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable throwable) {
                System.out.println(throwable.getMessage());
            }

            @Override
            public void onNext(Object o) {

            }
        });
        //不发布
        Observable.never().subscribe(System.out::println);
        //整数范围发布
        Observable.range(0, 3).subscribe(System.out::println);

        printLines();

        /*cache操作符:不能与无穷流配合,否则oom!,可以缓存一些init,只执行onNext,否则每次订阅create都会被重新执行*/
        final Observable<Object> cache = Observable.create(s -> {
            System.out.println("start create!");
            s.onNext(0);
            s.onCompleted();
        }).cache();

        cache.subscribe(System.out::println);
        cache.subscribe(System.out::println);

        /*无穷流*/
        final Observable<Object> naturalNumbers = Observable.create(s -> {
            Runnable r = () -> {
                BigInteger i = BigInteger.ZERO;
                //安全退出线程,true式不可取
                while (!s.isUnsubscribed()) {
                    s.onNext(i);
                    i = i.add(BigInteger.ONE);
                }
            };
            final Thread thread = new Thread(r);
            thread.start();
            s.add(Subscriptions.create(thread::interrupt));
        });

        naturalNumbers.subscribe(new Subscriber<>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable throwable) {

            }

            @Override
            public void onNext(Object o) {
                if (o instanceof BigInteger) {
                    final BigInteger o1 = (BigInteger) o;
                    System.out.println(o1 + "_" + getThreadName());
                    if (o1.equals(BigInteger.TEN)) {
                        unsubscribe();
                    }
                }
            }
        });

        printLines();

        /*异常下游*/
        Observable.create(s->{
            try {
                s.onNext(0);
                s.onCompleted();
            }catch (Exception e){
                //对可能抛出的异常,传递下游,而非简单打印
                s.onError(e);
            }
        });


        /*timer和interval*/
        //timer底层创建一个线程,1s后发出通知,接收一个long 0值,功能类似异步Thread.sleep(),返回0值只是一个约定
        Observable.timer(1, TimeUnit.SECONDS).subscribe(System.out::println);
        //Observable.interval()会从零开始生成一系列long类型的连续数字
        //与range()不同,interval()会在每个事件之前添加固定的时间间隔,包括第一个
        Observable.interval(1,TimeUnit.SECONDS)
                .subscribe(System.out::println);

        /*阻塞主进程*/
        while (true) ;
    }

}
        //向上链式订阅
        Observable.just(8, 9, 10)
                .doOnNext(i -> System.out.println("A: " + i)) // 打印一次推送,传递
                .filter(i -> i % 3 > 0)
                .doOnNext(i -> System.out.println("B: " + i))
                .map(i -> "#" + i * 10)
                .doOnNext(i -> System.out.println("C: " + i))
                .filter(s -> s.length() < 4)
                .subscribe(s -> System.out.println("D: " + s));

        /* 输出
        A: 8
        B: 8
        C: #80
        D: #80
        A: 9
        A: 10
        B: 10
        C: #100
        */

参考:

RxJava(一) create 操作符的用法和源码分析_Chiclaim-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值