专栏首页振兴的Android修炼手册小明要吃冰淇淋之RxJava:lift原理

小明要吃冰淇淋之RxJava:lift原理

前言

关于RxJava的基础心法解析

我们在使用 RxJava 的时候必不可少的会使用一些基础的操作符, mapflatMapfilter 等。这些都是对 Obserbable 进行各种各样的变化,我们查看其实现都能看到一个叫做 lift 的操作符。

lift源码

我们先看源码(rxjava:1.3.0),再通过一个例子来熟悉、掌握。

public interface Func1<T, R> extends Function {
    R call(T t);
}
//注意操作符的入参和出参都是Subscriber
public interface Operator<R, T> extends Func1<Subscriber<? super R>, Subscriber<? super T>> {
    // cover for generics insanity
}

public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) {
    //创建新的Observable,OnSubscribeLift代替原理的onSubscribe
    return unsafeCreate(new OnSubscribeLift<T, R>(onSubscribe, operator));
}

public final class OnSubscribeLift<T, R> implements OnSubscribe<R> {
    //上一层的Observable的onSubscribe
    final OnSubscribe<T> parent;
    //需要变换的操作符
    final Operator<? extends R, ? super T> operator;
    public OnSubscribeLift(OnSubscribe<T> parent, Operator<? extends R, ? super T> operator) {
        this.parent = parent;
        this.operator = operator;
    }
    @Override
    public void call(Subscriber<? super R> o) {
        try {
            //调用操作符的call方法,operator.call
            Subscriber<? super T> st = RxJavaHooks.onObservableLift(operator).call(o);
            try {
                st.onStart();
                parent.call(st);
            } catch (Throwable e) {
                Exceptions.throwIfFatal(e);
                st.onError(e);
            }
        } catch (Throwable e) {
            Exceptions.throwIfFatal(e);
            o.onError(e);
        }
    }
}

源码解读

以上为 lift 操作相关的代码,我们先不管泛型中的 RT 之类的,这种情况下根据泛型去推到容易让其更加的复杂。所以我们先简化一下代码:

public <R> Observable<R> lift(Operator<? extends R, ? super T> operator) {
    return Observable.create(new OnSubscribe<R>() {
        @Override
        public void call(Subscriber subscriber) {
            Subscriber newSubscriber = operator.call(subscriber);
            newSubscriber.onStart();
            onSubscribe.call(newSubscriber);
        }
    });
}

lift

图片来自:扔物线 - 给 Android 开发者的 RxJava 详解

简单的来看,以上过程产生了两个 ObservableOnSubscribe :

  • 创建了一个新的 Observable ;
  • 新的 Observable 的成员变量 onSubscribe 变化成了 OnSubscribeLift
  • 进过操作符 operator 变换之后的 newSubscribe ,变成的原来的 Obserbable 的订阅者;
  • 操作符 operator 之后的订阅者,订阅的是新的 Observable ;

整个实现 lift() 的过程,有点像一种代理机制,通过事件拦截和处理实现事件序列的变换。我们举个生活中的例子加深一下印象:

小明需要买一个冰淇淋,他不用去冰淇淋制造厂; 冰淇淋制造厂将制造出的冰淇淋,交给商店进行售卖; 商店进购了冰淇淋之后,买给了小明;

这里 商店 相当于一个 lift() 操作符。 小明 订阅 冰淇淋 的过程: 商店 订阅了 工厂冰淇淋小明 订阅了 商店冰淇淋

这么通俗的讲解相比大家都对 lift 已经印象非常深刻了吧!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Glide源码阅读理解一小时

    这篇图、文、表、代码一起组成的 Glide 源码分析的文章是在上一篇文章 Android-Universal-Image-Loader源码分析 中之后的又一篇图...

    静默加载
  • Android系统的编舞者Choreographer

    上一篇文章 Android的16ms和垂直同步以及三重缓存 解释了手机流畅性的问题,并在文章中提到了在Android4.1中添加的Vsync。Choreogra...

    静默加载
  • Android换肤原理和Android-Skin-Loader框架解析

    Android换肤技术已经是很久之前就已经被成熟使用的技术了,然而我最近才在学习和接触热修复的时候才看到。在看了一些换肤的方法之后,并且对市面上比较认可的And...

    静默加载
  • ExtJs学习笔记(11)_Absolute布局和Accordion布局

    ExtJs其实在某种程度上可以代替div+css来进行页面布局(不过经测试,在最新的Firefox3下,部分功能好象有点问题),今天我们来学习二种最基本的布局 ...

    菩提树下的杨过
  • 腾讯网新闻底层页无障碍代码细节

    本周一部署在新闻频道并得到可反馈和升级。 现已部署在新闻频道、财经频道、体育频道、娱乐频道、公益频道。 主要针对于盲人用户使用的屏幕阅读器在阅读新闻底层页(新闻...

    RP道貌不岸然
  • myeclipse 2017 CI 中如何修改Servlet模板

      在实际开发中,这些生成的代码和注释一般我们都用不到的,每次都要手工删除这些注释和代码,很麻烦,因此可以根据开发的实际情况修改Servlet的模板代码,改成符...

    黑泽君
  • 虚拟存储器

    week
  • Facebook为员工“开小灶”,创建AI学院分享知识

    镁客网
  • Email系列(QQ邮箱 + 含附件的邮箱案例 + 项目实战)下

    3.项目应用:https://github.com/dunitian/LoTCodeBase/tree/master/NetCode/3.常用技能/07.Ema...

    逸鹏
  • Azure认知服务之使用墨迹识别功能识别手写汉字

    前面我们使用Azure Face实现了人脸识别、使用Azure表格识别器提取了表格里的数据。这次我们试试使用Azure墨迹识别API来对笔迹进行识别。

    kklldog

扫码关注云+社区

领取腾讯云代金券