RxAndroid之Action,Func,map,flatmap的简单用法。

来源:互联网 发布:以上内容来源于网络 编辑:程序博客网 时间:2024/05/24 07:12

继续学习Rx,苦逼苦逼,感觉智商不够用了呢。
主要总结一下Action,Func,map,flatmap的简单用法,以及线程切换的使用。
原理,依然不明。

Action

场景:观察者输出一句被观察者传入的句子
还是萌新的时候,老老实实的用new Subscriber写吧

        Observable.just("我爱你")                .subscribe(new Subscriber<String>() {                    @Override                    public void onCompleted() {                    }                    @Override                    public void onError(Throwable e) {                    }                    @Override                    public void onNext(String s) {                        Log.i(TAG, s);                    }                });

用action之后的写法
二者是等价的
这里的原理”我觉得”是subscribe()自动将Action1里面的call方法转换成了Subscriber的onNext方法。

  Observable.just("我爱你")                .subscribe(new Action1<String>() {                    @Override                    public void call(String s) {                        Log.i(TAG, s);                    }                });

map和Func

二者放在一起是因为,我感觉他们两个就是一对儿cp。
场景:现在有一个家庭,家庭里面有两个人,我需要在传入家庭,而得到家庭成员
家庭的实体类如下

public class Home {    List<String> list;    public Home() {        list = new ArrayList<>();        list.add("王元姬");        list.add("司马昭");    }    public List<String> getList() {        return list;    }}

常规写法

 final Home home=new Home();        Observable.create(new Observable.OnSubscribe<List<String>>() {            @Override            public void call(Subscriber<? super List<String>> subscriber) {                subscriber.onNext(home.getList());            }        }).subscribe(new Action1<List<String>>() {            @Override            public void call(List<String> strings) {                for (String s :                        strings) {                    Log.i(TAG, s);                }            }        });

上面的写法很容易理解,Observable将家庭成员的集合添加到队列,而后subscriber用一个for循环将list里面的人员打印出来。

map和func的组合写法

Home home=new Home();        Observable.just(home)                .map(new Func1<Home, List<String>>() {                    @Override                    public List<String> call(Home home) {                        return home.getList();                    }                }).subscribe(new Action1<List<String>>() {                    @Override                    public void call(List<String> strings) {                        for (String s:strings) {                            Log.i(TAG, s);                        }                    }                });

二者的作用是一样的,可以看到map和func的组合使用,将参数home,改变成了一个list,整个事件的参数,也变成了list。这里称之为变换。
其实我们看到for循环很不爽,对吧,也许会想到,把一开始的just(home)改成from(home.getList()),然后用一个map(new Func1(){……}把list变换成String不就好了吗?但是很遗憾,map只能一一变换,也就是说,一个list是不能变换成多个String的。
于是乎,

flatMap的写法

 Home home=new Home();        Observable.just(home)                .flatMap(new Func1<Home, Observable<String>>() {                    @Override                    public Observable<String> call(Home home) {                        return Observable.from(home.getList());                    }                })                .subscribe(new Action1<String>() {                    @Override                    public void call(String s) {                        Log.i(TAG, s);                    }                });

看起来可能会很晕,但是仔细一想还是很容易理解的
要取得家庭成员里面的名字,从传入参数开始,需要经历几个步骤
传入home=1=》取得家庭成员集合= 2=》取得集合的元素
其实也就两步需要变换
map做了什么呢
map在第1步把home变成了集合,但是因为无法做到第2步,所以只能加入一个for循环在subscriber里面处理
既然1步做不到,那我就两步好了!
这个两步就是flatmap

现在来看一下flatpmap的做法

flatMap(new Func1<Home, Observable<String>>()

很眼熟吧,和map一样,其实都是把传入的参数Home,变换成了另外一个类型,当然,这里的类型不再是基本类型,居然是一个新的Observable,而这个Observable是什么样的呢
return Observable.from(home.getList());
这里,恍然大悟,我从原来的Observable里面又创建了一个Observable,由这个Observable来进行后续的事件

总结一下,整个事件经过了以下流程
Observable(1)传入home= =》faltMap拿到home= =》生成Observable(2)(醒目!!)= =》Observable(2)继续执行subscribe
而在变换Observable(2)(醒目!!)这一内部,又发生了home= =》String。
其实聪明如你一定想说,这什么玩意儿,明明可以一句话搞定的:

 Home home=new Home();        Observable.from(home.getList())                .subscribe(new Action1<String>() {                    @Override                    public void call(String s) {                        Log.i(TAG, s);                    }                });

确实如此,当然复杂的例子我一时半会也想不出来,感觉这样可以解释清楚flatMap的原理。

关于线程切换的简单说明

Observable.create(new Observable.OnSubscribe<Bitmap>() {            @Override            public void call(final Subscriber<? super Bitmap> subscriber) {                OkHttpClient client=new OkHttpClient();                client.newCall(new Request.Builder().url(PATH3).build())                        .enqueue(new Callback() {                            @Override                            public void onFailure(Call call, IOException e) {                            }                            @Override                            public void onResponse(Call call, Response response) throws IOException {                                byte[] data=response.body().bytes();                                Bitmap bitmap=BitmapFactory.decodeByteArray(data,0,data.length);                                subscriber.onNext(bitmap);                                subscriber.onCompleted();                            }                        });            }        }).subscribeOn(Schedulers.io())//产生subscribe指定在io线程          .observeOn(AndroidSchedulers.mainThread())//随后的动作在android主线程                .subscribe(new Action1<Bitmap>() {                    @Override                    public void call(Bitmap bitmap) {                        iMain.show(bitmap);                    }                });

抛开OkHttp的部分,这一段代码作的事情,简单来说,就是从网址拿到图片,再把图片加载到activity的imageView中
subscribeOn(Schedulers.io()) 这句话是常用的指定后台获取数据,网络访问通常比较耗时
一旦拿到数据
observeOn(AndroidSchedulers.mainThread()) 切换到主线程,更新UI。
关于subscribeOn和observeOn的具体原理以及区别我还没有弄懂。
以后搞懂了再说吧

0 0