RxJava中map方法的解析

本文详细解析了如何使用RxJava实现图像加载的过程,包括创建Observable对象、映射操作和订阅过程,以及如何将字符串路径转换为Bitmap图像并显示在ImageView中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有如下场景:给定一个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中显示。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值