Flow的4个接口
1、Publisher 发布者(数据发布)
public static interface Publisher<T> {
public void subscribe(Subscriber<? super T> subscriber);
}
- subscribe:接收订阅者,数据的流向者
2、Subscriber 订阅者(终端操作)
- onSubscribe:订阅者被发布者接收后,告知订阅者订阅成功
- onNext:数据的流动Sink
- onError:执行错误时的流向
- onComplete:数据执行完时的流向
public static interface Subscriber<T> {
public void onSubscribe(Subscription subscription);
public void onNext(T item);
public void onError(Throwable throwable);
public void onComplete();
}
3、Subscription 订阅(数据请求、取消)
- request:请求数据+个数,解决数据拥堵
- cancel:取消订阅,不再需要数据
public static interface Subscription {
public void request(long n);
public void cancel();
}
4、Processor 处理器(中间操作)
- 既是Subscriber也是Publisher,消费和下发数据
public static interface Processor<T,R> extends Subscriber<T>, Publisher<R> {
}
Publisher-Processor-Subscriber操作流程
- 绿色:订阅过程,Subscriber-Publisher向上关系
- 黑色:订阅成功,Publisher-Subscriber向下关系
- 蓝色:数据请求,Subscriber-Publisher向上关系
- 红色:数据分发,Publisher-Subscriber向下关系
例子:完成一连串的动作,数据下发—>按条件过滤—>数据转换—>数据消费
Publischer
- 接收Spliterator,完成数据下发(T)
public class FlowPublisher<T> implements Flow.Publisher<T>, Flow.Subscription {
private final Spliterator<T> spliterator;
private Flow.Subscriber<? super T> subscriber;
private boolean completed = false;
private boolean canceled = false;
public FlowPublisher(@NonNull Spliterator<T> spliterator) {
this.spliterator = spliterator;
}
@Override
public void subscribe(Flow.Subscriber<? super T> subscriber) {
this.subscriber = subscriber;
this.subscriber.onSubscribe(this);
}
@Override
public void request(long n) {
//已完成或已取消,则不再下发消息
if(completed || canceled) {
return;
}
//数据消息下发完,则下发onComplete消息
long size = spliterator.getExactSizeIfKnown();
if(size == 0) {
completed = true;
subscriber.onComplete();
return;
}
//下发数据消息
for(long i=Math.min(n, size); i>0; i--) {
spliterator.tryAdvance(subscriber::onNext);
}
}
@Override
public void cancel() {
canceled = true;
//取消后下发onComplete消息
if(!completed) {
subscriber.onComplete();
}
}
}
Processor:filter操作
- 接收Predicate,完成数据过滤(T->T)。数据被过滤,则继续向上请求直到下流请求数量满足或分发完成
public class FilterProcessor<T> implements Flow.Processor<T, T>, Flow.Subscription {
private final Predicate<T> predicate;
private Flow.Subscriber<? super T> subscriber;
private Flow.Subscription subscription;
private long requestCount;
private long leftCount;
public FilterProcessor(@NonNull Predicate<T> predicate) {
this.predicate = predicate;
}
@Override
public void subscribe(Flow.Subscriber<? super T> subscriber) {
this.subscriber = subscriber;
this.subscriber.onSubscribe(this);
}
@Override
public void onSubscribe(Flow.Subscription subscription) {
this.subscription = subscription;
}
@Override
public void onNext(T item) {
requestCount--;
if(predicate.test(item)) {
subscriber.onNext(item);
} else {
leftCount++;
}
if(requestCount == 0 && leftCount > 0) {
request(leftCount);
}
}
@Override
public void onError(Throwable throwable) {
subscriber.onError(throwable);
}
@Override
public void onComplete() {
subscriber.onComplete();
}
@Override
public void request(long n) {
leftCount = 0;
requestCount = n;
subscription.request(n);
}
@Override
public void cancel() {
subscription.cancel();
}
}
Processor:mapping操作
- 接收Function,完成数据转换(P->N)
public class MappingProcessor<P, N> implements Flow.Processor<P, N> {
private final Function<P, N> function;
private Flow.Subscriber<? super N> subscriber;
private Flow.Subscription subscription;
public MappingProcessor(@NonNull Function<P, N> function) {
this.function = function;
}
@Override
public void subscribe(Flow.Subscriber<? super N> subscriber) {
this.subscriber = subscriber;
this.subscriber.onSubscribe(subscription);
}
@Override
public void onSubscribe(Flow.Subscription subscription) {
this.subscription = subscription;
}
@Override
public void onNext(P item) {
subscriber.onNext(function.apply(item));
}
@Override
public void onError(Throwable throwable) {
subscriber.onError(throwable);
}
@Override
public void onComplete() {
subscriber.onComplete();
}
}
Subscriber:TerminalOp
- 接收Consumer,完成数消费(T)
public class FlowSubscriber<T> implements Flow.Subscriber<T> {
private final Consumer<T> consumer;
private Flow.Subscription subscription;
private boolean completed = false;
private long requestCount;
private static final long REQUEST_COUNT = 3;
public FlowSubscriber(@NonNull Consumer<T> consumer) {
this.consumer = consumer;
}
@Override
public void onSubscribe(Flow.Subscription subscription) {
requestCount = REQUEST_COUNT;
this.subscription = subscription;
this.subscription.request(requestCount);
}
@Override
public void onNext(T item) {
requestCount--;
consumer.accept(item);
if(requestCount == 0 && !completed) {
requestCount = REQUEST_COUNT;
subscription.request(requestCount);
}
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onComplete() {
requestCount = 0;
completed = true;
}
}
FlowHelper
- 把FlowPublisher、FilterProcessor、MappingProcessor、FlowSubscriber串联起来,完成链式操作
public class FlowHelper<T> {
private Flow.Publisher<T> publisher;
public static <E> FlowHelper<E> flow(@NonNull Spliterator<E> spliterator) {
return new FlowHelper<>(new FlowPublisher<>(spliterator));
}
private FlowHelper(@NonNull Flow.Publisher<T> publisher) {
this.publisher = publisher;
}
public FlowHelper<T> filter(@NonNull Predicate<T> predicate) {
FilterProcessor<T> p = new FilterProcessor<>(predicate);
publisher.subscribe(p);
publisher = p;
return this;
}
public <R> FlowHelper<R> mapping(@NonNull Function<T, R> function) {
MappingProcessor<T, R> p = new MappingProcessor<>(function);
publisher.subscribe(p);
return new FlowHelper<>(p);
}
public void accept(@NonNull Consumer<T> consumer) {
FlowSubscriber<T> s = new FlowSubscriber<>(consumer);
publisher.subscribe(s);
}
}
FlowTest测试
- 数据生成 Spliterator
- 数据过滤 filter:过滤掉非数字的字串
- 数据转换 mapping:String ---> FlowBean
- 数据消费:输出Log,显示结果:13689
public class FlowTest {
private final Pattern pattern;
public FlowTest() {
pattern = Pattern.compile("[0-9]*");
}
public void testFlow() {
List<String> list = List.of("1", "2a", "3", "4b", "5c", "6", "7d", "8", "9");
FlowHelper.flow(list.spliterator())
.filter(v -> pattern.matcher(v).matches())
.mapping(FlowBean::new)
.accept(FlowBean::print);
}
static class FlowBean {
final String result;
public FlowBean(String result) {
this.result = result;
}
public void print() {
Log.d("FlowTest", result);
}
}
}