现在很多Android App的开发开始使用Rxjava,但是Rxjava以学习曲线陡峭著称,入门有些困难。经过一段时间的学习和使用,这里来介绍一下我对Rxjava的理解。

  说到Rxjava首先需要了解的两个东西,一个是Observable(被观察者,事件源)和 Subscriber(观察者,是 Observer的子类)。Observable发出一系列事件,Subscriber处理这些事件。首先来看一个基本的例子,我们如何创建并使用Observable。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Observable.create(new Observable.OnSubscribe<String>() {
    @Override public void call(Subscriber<? super String> subscriber) {
        subscriber.onNext("hello");
        }
    }).subscribe(new Subscriber<String>()
    {
        @Override public void onCompleted() {
        }
        @Override public void onError(Throwable e) {
        }
        @Override public void onNext(String s) {
            Log.d("rx-info", s);
        }
    });

  创建Observable的最基本的方法是通过Observable.create() 来进行,当有Subscriber通过Observable.subscribe() 方法进行订阅之后Observable就会发射事件,注意必须要有订阅者订阅才会发射事件。发射的方式是通过调用 Observable中的 OnSubsribe 类型的成员来实现(每个Observable有一个final OnSubscribe<T> onSubscribe 成员,该成员是一个接口,后面详细说),在 Onsubsribe类型成员中调用 call() 方法,注意,这个call方法的参数就是 Observable.subscribe() 方法传入的 Subsriber实例。总的一句话就是在Obsubscribe 的 call方法中执行订阅者(Subscriber)的三个方法 onNext(), onCompleted() 和 onError()。

  一开始就是一堆 Observable , Subscriber,subscribe() , OnSubscribe 估计看得头晕,因此我们需要先来对这些东西有一个了解。这里只列出一个帮助理解的大概。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Observable<T> {
 
      final OnSubscribe<T> onSubscribe;
      protected Observable(OnSubscribe<T> f) {
              this.onSubscribe = f;
          }
 
       public final static <T> Observable<T> create(OnSubscribe<T> f) {
            return new Observable<T>(hook.onCreate(f));
        }
 
       public interface OnSubscribe<T> extends Action1<Subscriber<? super T>> {
            // cover for generics insanity
        }
     
      public final Subscription subscribe(Subscriber<? super T> subscriber) {
              return Observable.subscribe(subscriber, this);
          }
 
       public interface Operator<R, T> extends Func1<Subscriber<? super R>, Subscriber<? super T>> {
        // cover for generics insanity
       }
}
1
2
3
public interface Action1<T> extends Action {
    void call(T t);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public interface Subscription {
    void unsubscribe();
    boolean isUnsubscribed();
}
public interface Observer<T> {
    void onCompleted();
    void onError(Throwable e);
    void onNext(T t);
}
 
public abstract class Subscriber<T> implements Observer<T>, Subscription {
    //...
}

  通过上面的代码帮助理清楚 Observable, Observer, Subscriber, OnSubsriber, subscribe() 之间的关系。这里额外提一下 Observable.subscribe() 方法有多个重载:

1
2
3
4
5
6
Subscription    subscribe()
Subscription    subscribe(Action1<? super  T> onNext)
Subscription    subscribe(Action1<? super  T> onNext, Action1< java.lang .Throwable> onError)
Subscription    subscribe(Action1<? super  T> onNext, Action1< java.lang .Throwable> onError, Action0 onComplete)
Subscription    subscribe(Observer<? super  T> observer)
Subscription    subscribe(Subscriber<? super  T> subscriber)

  其它的ActionX 和 FuncX 请大家自行去查阅定义。

  介绍了基本的创建Observable和 Observable是怎么发射事件的之后,来介绍一下Rxjava的Operator和Operator的原理。

  Rxjava的Operator常见的有map, flatMap, concat, merge之类的。这里就不介绍Operator的使用了,介绍一下其原理。介绍原理还是来看源码,以map为例。

  首先看一下使用map的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Observable.create(new Observable.OnSubscribe<String>() {
    @Override
    public void call(Subscriber<? super String> subscriber) {
        subscriber.onNext("hello");
    }
})
.map(new Func1<String, String>() {
    @Override
    public String call(String s) {
        return s + "word";
    }
})
.subscribe(new Subscriber<String>() {
    @Override
    public void onCompleted() {
 
    }
 
    @Override
    public void onError(Throwable e) {
 
    }
 
    @Override
    public void onNext(String s) {
        Log.d("info-rx", s);
    }
});

  继续来看 map的定义:

1
2
3
public final <R> Observable<R> map(Func1<? super T, ? extends R> func) {
    return lift(new OperatorMap<T, R>(func));
}

  简单说一下Func1,其中的T表示传入的参数类型,R表示方法返回的参数类型。Operator的操作原理最核心的就是lift的实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) {
    return new Observable<R>(new OnSubscribe<R>() {
        @Override
        public void call(Subscriber<? super R> o) {
            try {
                Subscriber<? super T> st = hook.onLift(operator).call(o);
                try {
                    // new Subscriber created and being subscribed with so 'onStart' it
                    st.onStart();
                    onSubscribe.call(st);
                } catch (Throwable e) {
                    // localized capture of errors rather than it skipping all operators
                    // and ending up in the try/catch of the subscribe method which then
                    // prevents onErrorResumeNext and other similar approaches to error handling
                    Exceptions.throwIfFatal(e);
                    st.onError(e);
                }
            } catch (Throwable e) {
                Exceptions.throwIfFatal(e);
                // if the lift function failed all we can do is pass the error to the final Subscriber
                // as we don't have the operator available to us
                o.onError(e);
            }
        }
    });
}

  lift方法看起来太过复杂,稍作简化:

1
2
3
public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) {
    return new Observable<R>(...);
}

  lift方法实际是产生一个新的 Observable。在map()调用之后,我们操作的就是新的Observable对象,我们可以把它取名为Observable$2,我们这里调用subscribe就是Observable$2.subscribe,继续看到subscribe里,重要的几个调用:

1
2
hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber);
return hook.onSubscribeReturn(subscriber);

  注意,这里的observable是Observable$2!!也就是说,这里的onSubscribe是,lift中定义的!!

  回过头来看lift方法中创建新Observable的过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
return new Observable<R>(new OnSubscribe<R>() {
    @Override
    public void call(Subscriber<? super R> o) {
        try {
            Subscriber<? super T> st = hook.onLift(operator).call(o);
            try {
                // new Subscriber created and being subscribed with so 'onStart' it
                st.onStart();
                onSubscribe.call(st); //请注意我!! 这个onSubscribe是原始的OnSubScribe对象!!
            } catch (Throwable e) {
                // localized capture of errors rather than it skipping all operators
                // and ending up in the try/catch of the subscribe method which then
                // prevents onErrorResumeNext and other similar approaches to error handling
                if (e instanceof OnErrorNotImplementedException) {
                    throw (OnErrorNotImplementedException) e;
                }
                st.onError(e);
            }
        } catch (Throwable e) {
            if (e instanceof OnErrorNotImplementedException) {
                throw (OnErrorNotImplementedException) e;
            }
            // if the lift function failed all we can do is pass the error to the final Subscriber
            // as we don't have the operator available to us
            o.onError(e);
        }
    }
});

  一定一定要注意这段函数执行的上下文!,这段函数中的onSubscribe对象指向的是外部类,也就是第一个Observable的onSubScribe!而不是Observable$2中的onSubscribe,接下来看:

1
Subscriber<? super T> st = hook.onLift(operator).call(o);

  这行代码,就是定义operator,生成一个经过operator操作过的Subscriber,看下OperatorMap这个类中的call方法: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Override
public Subscriber<? super T> call(final Subscriber<? super R> o) {
    return new Subscriber<T>(o) {
 
        @Override
        public void onCompleted() {
            o.onCompleted();
        }
 
        @Override
        public void onError(Throwable e) {
            o.onError(e);
        }
 
        @Override
        public void onNext(T t) {
            try {
                o.onNext(transformer.call(t));
            } catch (Throwable e) {
                Exceptions.throwIfFatal(e);
                onError(OnErrorThrowable.addValueAsLastCause(e, t));
            }
        }
 
    };
}

  没错,对传入的Subscriber做了一个代理,把转换后的值传入。这样就生成了一个代理的Subscriber,最后我们最外层的OnSubscribe对象对我们代理的Subscriber进行了调用: 

1
2
3
4
5
@Override
public void call(Subscriber<? super String> subscriber) {
    //此处的subscriber就是被map包裹(wrapper)后的对象。
    subscriber.onNext("hello");
}

  然后这个subscriber传入到内部,链式的通知,最后通知到我们在subscribe函数中定义的对象。

  分析lift的原理,其实还是回到了一开始介绍的Observable必须要有订阅者进行订阅才能发射事件。lift方法会产生一个新的Observable,并且这个Observable位于原始Observable和后面的Subsriber之间,因此lift方法也需要提供一个新的Subscriber来使得新产生的Observable发射事件,这个新的Subsriber就是对事件链后方的Subscriber就行包装做一个代理。

  详细使用Rxjava可参见:

  1. 给 Android 开发者的 RxJava 详解

  2.Rxjava使用基础合集

 

posted @ 2016-02-24 22:27 KingsLanding 阅读(1369) 评论(0) 推荐(0) 编辑
摘要: Android开发网络通信一开始的时候使用的是AsyncTask封装HttpClient,没有使用原生的HttpURLConnection就跳到了Volley,随着OkHttp的流行又开始迁移到OkHttp上面,随着Rxjava的流行又了解了Retrofit,随着Retrofit的发展又从1.x到了 阅读全文
posted @ 2016-01-31 11:43 KingsLanding 阅读(2466) 评论(0) 推荐(0) 编辑
摘要: Square 为广大开发者奉献了OkHttp,Retrofit1.x,Retrofit2.x,运用比较广泛,这三个工具有很多相似之处,初学者可能会有一些使用迷惑。这里来总结一下它们的一些基本使用和一些细微差别。 /************** Retrofit 基本使用方法 Retrofit 到底是 阅读全文
posted @ 2016-01-30 14:52 KingsLanding 阅读(1422) 评论(0) 推荐(0) 编辑
摘要: 接上一篇文章介绍了Dagger2的初步使用,相信刚接触的人会觉得很奇怪,怎么会有很多自己没有定义的代码出现,为什么Component的创建方式是那样的。为了搞清楚这些东西,我们需要查看一下Dagger2 生成的源代码。Dagger2 是一个DI框架,通过学习生成的代码也可以更好的理解Dagger... 阅读全文
posted @ 2016-01-11 21:15 KingsLanding 阅读(3122) 评论(1) 推荐(0) 编辑
摘要: Dagger2 是一个Android依赖注入框架,由谷歌开发,最早的版本Dagger1 由Square公司开发。依赖注入框架主要用于模块间解耦,提高代码的健壮性和可维护性。Dagger 这个库的取名不仅仅来自它的本意“匕首”,同时也暗示了它的原理。Jake Wharton 在对 Dagger 的介绍 阅读全文
posted @ 2016-01-10 22:29 KingsLanding 阅读(38027) 评论(26) 推荐(1) 编辑
摘要: 接上一篇,搭建好基于Android Studio的环境之后,编写native代码相对来说也比较简单了。在Android上编写Native代码和在Linux编写C/C++代码还是有区别,Native代码一般需要与JVM交互数据,需要遵循一定的规范,本文来介绍一下基本的JNI代码写法。 我们还是从... 阅读全文
posted @ 2015-11-19 22:40 KingsLanding 阅读(2014) 评论(0) 推荐(0) 编辑
摘要: 从Eclipse时代到Android Studio普及,开发工具越来越好用。早些时候还需要安装Cygwin工具,从Android Studio1.3以后,在Android 环境开发JNI程序搭建开发环境变得相对简单。这里就来介绍一下急于Android Studio如何进行jni开发。 首先准备... 阅读全文
posted @ 2015-11-18 22:30 KingsLanding 阅读(14227) 评论(1) 推荐(1) 编辑
摘要: Android 触摸事件的处理主要涉及到几个方法:onInterceptTouchEvent(), dipatchTouchEvent(), onTouchEvent(), onTouch()。 onInterceptTouchEvent() 用于拦截事件并改变事件传递方向。解释一下事件传递。... 阅读全文
posted @ 2015-06-15 22:18 KingsLanding 阅读(6123) 评论(0) 推荐(0) 编辑
摘要: Android Dev Tools官网地址:www.androiddevtools.cn收集整理Android开发所需的Android SDK、开发中用到的工具、Android开发教程、Android设计规范,免费的设计素材等。欢迎大家推荐自己在Android开发过程中用的好用的工具、学习开发教程、... 阅读全文
posted @ 2015-06-07 19:52 KingsLanding 阅读(28617) 评论(0) 推荐(8) 编辑
摘要: Android 上使用Opengl进行滤镜渲染效率较高,比起单纯的使用CPU给用户带来的体验会好很多。滤镜的对象是图片,图片是以Bitmap的形式表示,Opengl不能直接处理Bitmap,在Android上一般是通过GLSurfaceView来进行渲染的,也可以说成Android需要借助GLS... 阅读全文
posted @ 2015-05-24 21:16 KingsLanding 阅读(26963) 评论(0) 推荐(0) 编辑
点击右上角即可分享
微信分享提示