您的位置:首页 > 编程语言 > Java开发

深入浅出RxJava—操作符

2017-08-29 14:56 441 查看
原文链接

参考文章

本篇文章将重点介绍RxJava中的操作符,RxJava的强大性就来于它所定义的操作符。

假如我们现在有这样一个接口,返回一个网站地址list集合,并将集合数据进行打印,基于上一篇文章,我们可能写出这样的代码:

先贴出query方法代码:

1
public Observable<List<String>> query() {
2
3
List<String> list = new ArrayList<>();
4
list.add("baidu");
5
list.add("youku");
6
list.add("iqiyi");
7
list.add("sohu");
8
list.add("");
9
10
return Observable.just(list);
11
}
查询将输入地址:



1

query().subscribe(new Action1<List<String>>() {


2

@Override


3

public void call(List<String> list) {


4



5

for (String s : list) {


6

Toast.makeText(MainActivity.this, s, Toast.LENGTH_LONG).show();


7

}


8

}


9

});


这段代码使我们丢失了变换数据流的能力,一但要更改数据只能在subscribe 总进行,那你会说可以使用map操作符:

1
query().map(new Func1<List<String>, String>() {
2
@Override
3
public String call(List<String> list) {
4
for (String s : list) {
5
return s;
6
}
7
return null;
8
}
9
}).subscribe(new Action1<String>() {
10
@Override
11
public void call(String s) {
12
Toast.makeText(MainActivity.this, s, Toast.LENGTH_LONG).show();
13
}
14
});
这样的代码依旧要使用集合遍历的方式才能获取到每一个元素。幸运的是RxJava提供了另外一个方法from,它接受一个集合作为输入,然后每次输出一个元素给subscriber。



1

query().subscribe(new Action1<List<String>>() {


2

@Override


3

public void call(List<String> list) {


4

Observable.from(list).subscribe(new Action1<String>() {


5

        @Override


6

        public void call(String s) {


7

    Toast.makeText(MainActivity.this, s, Toast.LENGTH_LONG).show();


8

}


9

});


10

}


11

});


这样虽然去掉了遍历循环,但是代码看起来依然很凌乱,多个嵌套的subscription看起来很臃肿且不好维护。
救星来了,它就是flatMap,Observable.flatMap()接受一个Observable 为输入参数,同时输出另外一个Observable,直接上代码:

1
query().flatMap(new Func1<List<String>, Observable<String>>() {
2
@Override
3
public Observable<String> call(List<String> list) {
4
return Observable.from(list);
5
}
6
}).subscribe(new Action1<String>() {
7
@Override
8
public void call(String s) {
9
Toast.makeText(MainActivity.this, s, Toast.LENGTH_LONG).show();
10
}
11
});
理解flatMap的关键点在于,flatMap输出的Observable的泛型类型正是我们在subscriber 想要接受的。
继续,我们我们根据query查询的网址打印出其对应的title,要怎么做呢?先上getTilte(String title)的代码:



1

private Observable<String> getTitle(String url) {


2



3

Observable<String> observable = Observable.empty();


4



5

switch (url) {


6

case "baidu":


7

observable = Observable.just("百度");


8

break;


9

case "youku":


10

observable = Observable.just("优酷");


11

break;


12

case "iqiyi":


13

observable = Observable.just("爱奇艺");


14

break;


15

case "sohu":


16

observable = Observable.just("搜狐");


17

break;


18

case "":


19

observable = Observable.just(null);


20

break;


21

}


22



23

return observable;


24

}


上代码:

1
query().flatMap(new Func1<List<String>, Observable<String>>() {
2
@Override
3
public Observable<String> call(List<String> list) {
4
return Observable.from(list);
5
}
6
}).flatMap(new Func1<String, Observable<String>>() {
7
@Override
8
public Observable<String> call(String s) {
9
return getTitle(s);
10
}
11
}).subscribe(new Action1<String>() {
12
@Override
13
public void call(String s) {
14
Toast.makeText(MainActivity.this, s, Toast.LENGTH_LONG).show();
15
}
16
});

我们可以一直使用flatMap操作符来变换数据直到是subscriber想要的数据类型为止。在测试代码中有些返回的数据是null ,那我们怎么过滤这些数据呢?另一个操作符闪亮登场,它就是filter,



1

query().flatMap(new Func1<List<String>, Observable<String>>() {


2

@Override


3

public Observable<String> call(List<String> list) {


4

return Observable.from(list);


5

}


6

}).flatMap(new Func1<String, Observable<String>>() {


7

@Override


8

public Observable<String> call(String s) {


9

return getTitle(s);


10

}


11

}).filter(new Func1<String, Boolean>() {


12

@Override


13

public Boolean call(String title) {


14

return title != null;


15

}


16

}).subscribe(new Action1<String>() {


17

@Override


18

public void call(String s) {


19

Toast.makeText(MainActivity.this, s, Toast.LENGTH_LONG).show();


20

}


21

});


filter()输出和输入相同的元素,并且会过滤掉那些不满足检查条件的。这样,就将title为null的值给过滤掉了。现在输出的是4个结果了,那如果我们只想要前两个结果怎么办呢?
这就引入了另外一个操作符了,take,上代码:

1
query().flatMap(new Func1<List<String>, Observable<String>>() {
2
@Override
3
public Observable<String> call(List<String> list) {
4
return Observable.from(list);
5
}
6
}).flatMap(new Func1<String, Observable<String>>() {
7
@Override
8
public Observable<String> call(String s) {
9
return getTitle(s);
10
}
11
}).filter(new Func1<String, Boolean>() {
12
@Override
13
public Boolean call(String title) {
14
return title != null;
15
}
16
}).take(2).subscribe(new Action1<String>() {
17
@Override
18
public void call(String s) {
19
Toast.makeText(MainActivity.this, s, Toast.LENGTH_LONG).show();
20
}
21
});
take()输出最多指定数量的结果。另外,我们我们在最终输出结果之前还想对数据做一些操作,别如将title保存起来,这就要使用另一个操作符了,doOnNext:



1

query().flatMap(new Func1<List<String>, Observable<String>>() {


2

@Override


3

public Observable<String> call(List<String> list) {


4

return Observable.from(list);


5

}


6

}).flatMap(new Func1<String, Observable<String>>() {


7

@Override


8

public Observable<String> call(String s) {


9

return getTitle(s);


10

}


11

}).filter(new Func1<String, Boolean>() {


12

@Override


13

public Boolean call(String title) {


14

return title != null;


15

}


16

}).take(2).doOnNext(new Action1<String>() {


17

@Override


18

public void call(String s) {


19

saveTitle(s);


20

}


21

}).subscribe(new Action1<String>() {


22

@Override


23

public void call(String s) {


24

Toast.makeText(MainActivity.this, s, Toast.LENGTH_LONG).show();


25

}


26

});


doOnNext()允许我们在每次输出一个元素之前做一些额外的事情,比如这里的保存标题。

本篇主要讲了这么几个操作符,RxJava提供的操作符实在是很强大的,还可以自定义操作符。将一系列的操作符链接起来就可以完成复杂的逻辑。代码被分解成一系列可以组合的片段。这就是响应式函数编程的魅力。用的越多,就会越多的改变你的编程思维。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息