有如下场景:给定一个String类型的路径,以Bitmap类型在ImageView中显示该图像。
利用RxJava加载需要几个对象Subscriber, Observable.OnSubscribe和一个Func1。
subscriber = new Subscriber<Bitmap>(){
@Override
public void onCompleted() {
Toast.makeText(MainActivity.this, "",Toast.LENGTH_SHORT).show();
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Bitmap bitmap) {
ImageView iv = (ImageView)findViewById(R.id.iv);
iv.setImageBitmap(bitmap);
}
};
onSubscribe = new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> _subscriber) {
String s =Environment.getExternalStorageDirectory().
getAbsolutePath() + "/mypic/d.jpg";
_subscriber.onNext(s);
}
};
transform = new Func1<String, Bitmap>() {
@Override
public Bitmap call(String s) {
Bitmap bitmap = BitmapFactory.decodeFile(s);
return bitmap;
}
};
接下来写一个调用链:
subscription =Observable.create(onSubscribe).map(transform).subscribe(subscriber);
subscription是Subscription类型,用来取消注册的。
本文的主要目的是把Observable.create(onSubscribe).map(transform).subscribe(subscriber)进行拆解分析。
如果不用调用链的方式,可以上面那句话拆成三句话来写:
Observable observable1 = Observable.create(onSubscribe);
Observable observable2 = observable1.map(transform);
observable2.subscribe(subscriber);
一共有两个Observable对象,而且subscriber的subscribe是发生在observable2这个对象上。
observable2对象是通过map方法创建的,看一下map方法的源码:
public final<R> Observable<R> map(Func1<? super T, ? extends R> func) {
return this.lift(new OperatorMap(func));
}
map方法是调用了lift方法,并返回了lift方法的返回值。
lift方法的参数是一个OperatorMap对象,创建OperatorMap对象时需要一个Func1对象。
看一下OperatorMap的源码:
public final class OperatorMap<T, R>implements Operator<R, T> {
private final Func1<? super T, ? extends R> transformer;
public OperatorMap(Func1<? super T, ? extends R> transformer) {
this.transformer = transformer;
}
public Subscriber<? super T> call(final Subscriber<? superR> o) {
return new Subscriber(o) {
public void onCompleted() {
o.onCompleted();
}
public void onError(Throwable e) {
o.onError(e);
}
public void onNext(T t) {
try {
o.onNext(OperatorMap.this.transformer.call(t));
} catch (Throwable var3) {
Exceptions.throwOrReport(var3, this, t);
}
}
};
}
}
OperatorMap实现了Operator接口,那么再看一下Operator接口的内容:
public interface Operator<R, T>extends Func1<Subscriber<? super R>, Subscriber<? super T>>{}
Operator接口继承自Func1接口,没有做任何的方法扩展,只是做了一下泛型的整理(源码的注释是cover for generics insanity)。
看一下Func1的内容:
public interface Func1<T, R> extendsFunction {
Rcall(T var1);
}
Func1里面只有一个call方法,call方法接收T类型参数返回一个R类型的对象。Operator接口继承的是Func1<Subscriber<? super R>, Subscriber<? super T>>,Subscriber<?super R>与Subscriber<? super T>对应Func1接口定义中的两个泛型,但是R与T的类型此时还无法确定,所以把R与T做为Operator的泛型,在创建具体的Operator对象时指定R与T的类型。
对于OperatorMap来说实现Operator接口只要实现call方法即可。
OperatorMap第一个需要注意的是泛型的顺序,OperatorMap<T,R>实现的是Operator<R,T>接口,另外它有一个Func1<T, R>类型的属性transformer,在构建OperatorMap对象的时候必须为这个属性赋值,原因看OperatorMap对call方法的实现:
因为OperatorMap<T,R>实现的是Operator<R,T>接口,那么实现的call方法接收的是Subscriber<? super R>类型的参数而返回Subscriber<?super T>类型:
public Subscriber<? super T>call(final Subscriber<? super R> o) {
return new Subscriber(o) {
public void onCompleted() {
o.onCompleted();
}
public void onError(Throwable e) {
o.onError(e);
}
public void onNext(T t) {
try {
o.onNext(OperatorMap.this.transformer.call(t));
} catch (Throwable var3) {
Exceptions.throwOrReport(var3, this, t);
}
}
};
}
可以看到,返回的Subscriber<? super T>基本就是一个代理的角色,它的onError,onCompleted和onNext方法的具体工作都是由Subscriber<?super R>来完成的,只不过在onNext方法时,Subscriber<? super T>的onNext处理的参数类型是T而Subscriber<?super R>的onNext处理的参数类型是R,因此需要将T转为R,这恰好就是OperatorMap的Func1<T,R>做的工作!这就是为什么构建OperatorMap<T,R>对象要求必须传入一个Func1<T,R>对象的原因。
了解了OperatorMap之后,再看一下lift方法:
public final <R> Observable<R>lift(final Observable.Operator<? extends R, ? super T> operator) {
return new Observable(new Observable.OnSubscribe() {
public void call(Subscriber<? super R> o) {
try {
Subscriber e =(Subscriber)Observable.hook.onLift(operator).call(o);
try {
e.onStart();
Observable.this.onSubscribe.call(e);
} catch (Throwable var4) {
Exceptions.throwIfFatal(var4);
e.onError(var4);
}
} catch (Throwable var5) {
Exceptions.throwIfFatal(var5);
o.onError(var5);
}
}
});
}
lift方法的参数是一个Operator<R,T>类型,所以我们传入OperatorMap<T,R>对象作为lift参数,lift的返回值是一个Observable<R>类型对象。
创建一个Observable类型对象时必须传入一个OnSubscribe对象,当有订阅者订阅时,会触发这个OnSubscribe对象的call方法,同时订阅者会以参数的形式传入call方法中。lift这个方法创建的Observable对象的OnSubscribe是怎样的呢?
new Observable.OnSubscribe() {
public void call(Subscriber<? super R> o) {
try {
Subscriber<? super T>e =
(Subscriber)Observable.hook.onLift(operator).call(o);
try {
e.onStart();
Observable.this.onSubscribe.call(e);
} catch (Throwable var4) {
Exceptions.throwIfFatal(var4);
e.onError(var4);
}
} catch (Throwable var5) {
Exceptions.throwIfFatal(var5);
o.onError(var5);
}
}
}
onLift(operator)的默认实现就是返回operator本身,进而onLift(operator).call(o)实际就是operator.call(o)。o是介时订阅该Observable对象的Subscriber,通过上面关于OperatorMap的分析,operator.call(o)会返回一个Subscriber<?super T>订阅者e来代理Subscriber<? super R> o这个原始订阅者。代码继续向下,执行e的onStart方法,OperatorMap的call方法默认没有对onStart方法做过改动,所以这里执行e的onStart方法默认行为(onStart方法是一个空方法),接下来执行Observable.this.onSubscribe.call(e);这里需要注意的是Observable.this指代的是当前Observable对象,此时谁是Observable当前对象呢?我们把前面的三句执行代码拿到这里:
Observable observable1 = Observable.create(onSubscribe);
Observable observable2 = observable1.map(transform);
observable2.subscribe(subscriber);
observable1调用map方法,map方法中调用lift方法,lift方法中创建一个新的Observable对象(也就是observable2),所以当前Observable对象只的是调用map方法的Observable对象,也就是observable1。那么Observable.this.onSubscribe.call(e)的意思就是调用observable1中的onSubscribe属性的call方法,并将e这个订阅者传入。
OK,下面结合我前面的代码实现,把整体流程跑一遍:
observable2调用subscribe方法并传入subscriber<Bitmap>,这样就触发了observale2的onSubscribe的call方法,这个call方法先根据传入的subscriber<Bitmap>获得一个代理性质的subscriber<String>,然后调用observable1的onSubscribe的call方法并将subscriber<String>作为参数传入。observable1.OnSubscribe.call方法把一个String类型的路径传递给subscriber<String>的onNext方法,subscriber<String>的onNext只是一个代理,在这个onNext方法中利用transform将String格式的路径转为Bitmap图像后交给subscriber<Bitmap>的onNext方法做真正的处理。subscriber<Bitmap>的onNext方法中,会把该bitmap图形放到ImageView中显示。