将一个Observable分拆为一些Observables集合,它们中的每一个发射原始Observable的一个 子序列,哪个数据项由哪一个Observable发射是由一个函数判定 的,这个函数给每一项指定一个Key,Key相同的数据会被同一个Observable发射.
demo
Observable.range(1, 8).groupBy(new Func1<Integer, String>() {
@Override
public String call(Integer integer) {
return (integer % 2 == 0) ? "偶数组" : "奇数组";
}
}).subscribe(new Action1<GroupedObservable<String, Integer>>() {
@Override
public void call(final GroupedObservable<String, Integer> stringIntegerGroupedObservable) {
System.out.println("group name:" + stringIntegerGroupedObservable.getKey());
if (stringIntegerGroupedObservable.getKey().equalsIgnoreCase("奇数组"))
stringIntegerGroupedObservable.subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
System.out.println(stringIntegerGroupedObservable.getKey() + "'member: " + integer);
}
});
}
});
输出:
group name:奇数组
奇数组'member: 1
group name:偶数组
奇数组'member: 3
奇数组'member: 5
奇数组'member: 7
这里我们分成两组,并输出了其中一组的成员。下面我们看一下groupBy函数
public final <K> Observable<GroupedObservable<K, T>> groupBy(final Func1<? super T, ? extends K> keySelector) {
return lift(new OperatorGroupBy<T, K, T>(keySelector));
}
创建了一个OperatorGroupBy,传递keySelector用来区分分组
public OperatorGroupBy(Func1<? super T, ? extends K> keySelector) {
this(keySelector, (Func1)UtilityFunctions.<T>identity(), RxRingBuffer.SIZE, false, null);
}
public OperatorGroupBy(Func1<? super T, ? extends K> keySelector, Func1<? super T, ? extends V> valueSelector, int bufferSize, boolean delayError, Func1<Action1<K>, Map<K, Object>> mapFactory) {
this.keySelector = keySelector;
this.valueSelector = valueSelector;
this.bufferSize = bufferSize;
this.delayError = delayError;
this.mapFactory = mapFactory;
}
groupBy函数创建了一个Observable,Observable的onSubscribe是OnSubscribeLift ,OnSubscribeLift的operator是OperatorGroupBy
在后面subscribe的时候OnSubscribeLift的call
public void call(Subscriber<? super R> o) {
try {
Subscriber<? super T> st = RxJavaHooks.onObservableLift(operator).call(o);
try {
// new Subscriber created and being subscribed with so 'onStart' it
st.onStart();
parent.call(st);
} catch (Throwable e) {
// localized capture of errors rather than it skipping all operators
// and ending up in the try/catch of the subscribe method which then
// prevents onErrorResumeNext and other similar approaches to error handling
Exceptions.throwIfFatal(e);
st.onError(e);
}
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
// if the lift function failed all we can do is pass the error to the final Subscriber
// as we don't have the operator available to us
o.onError(e);
}
}
这里会调用OperatorGroupBy的call
public Subscriber<? super T> call(Subscriber<? super GroupedObservable<K, V>> child) {
final GroupBySubscriber<T, K, V> parent; // NOPMD
try {
parent = new GroupBySubscriber<T, K, V>(child, keySelector, valueSelector, bufferSize, delayError, mapFactory);
} catch (Throwable ex) {
//Can reach here because mapFactory.call() may throw in constructor of GroupBySubscriber
Exceptions.throwOrReport(ex, child);
Subscriber<? super T> parent2 = Subscribers.empty();
parent2.unsubscribe();
return parent2;
}
child.add(Subscriptions.create(new Action0() {
@Override
public void call() {
parent.cancel();
}
}));
child.setProducer(parent.producer);
return parent;
}
这里会创建一个GroupBySubscriber的订阅者,child是demo中最初的订阅者
public GroupBySubscriber(Subscriber<? super GroupedObservable<K, V>> actual, Func1<? super T, ? extends K> keySelector,
Func1<? super T, ? extends V> valueSelector, int bufferSize, boolean delayError,
Func1<Action1<K>, Map<K, Object>> mapFactory) {
this.actual = actual;
this.keySelector = keySelector;
this.valueSelector = valueSelector;
this.bufferSize = bufferSize;
this.delayError = delayError;
this.queue = new ConcurrentLinkedQueue<GroupedObservable<K, V>>();
this.s = new ProducerArbiter();
this.s.request(bufferSize);
this.producer = new GroupByProducer(this);
this.cancelled = new AtomicBoolean();
this.requested = new AtomicLong();
this.groupCount = new AtomicInteger(1);
this.wip = new AtomicInteger();
if (mapFactory == null) {
this.groups = new ConcurrentHashMap<Object, GroupedUnicast<K, V>>();
this.evictedKeys = null;
} else {
this.evictedKeys = new ConcurrentLinkedQueue<K>();
this.groups = createMap(mapFactory, new EvictionAction<K>(evictedKeys));
}
}
创建一个producer,类型是GroupByProducer,bufferSize是128,这里调用request最终会把requested变量设置为128
回到call, 调用
child.setProducer(parent.producer);
最终会调用producer的request,这里没做什么事,最终把刚生成的GroupBySubscriber返回
回到OnSubscribeLift的call,最终调用OnSubscribeRange
最终会调用RangeProducer的request
public void request(long requestedAmount) {
if (get() == Long.MAX_VALUE) {
// already started with fast-path
return;
}
if (requestedAmount == Long.MAX_VALUE && compareAndSet(0L, Long.MAX_VALUE)) {
// fast-path without backpressure
fastPath();
} else if (requestedAmount > 0L) {
long c = BackpressureUtils.getAndAddRequest(this, requestedAmount);
if (c == 0L) {
// backpressure is requested
slowPath(requestedAmount);
}
}
}
这里requestedAmount是128,走slowPath
void slowPath(long requestedAmount) {
long emitted = 0L;
long endIndex = endOfRange + 1L;
long index = currentIndex;
final Subscriber<? super Integer> childSubscriber = this.childSubscriber;
for (;;) {
while (emitted != requestedAmount && index != endIndex) {
if (childSubscriber.isUnsubscribed()) {
return;
}
childSubscriber.onNext((int)index);
index++;
emitted++;
}
if (childSubscriber.isUnsubscribed()) {
return;
}
if (index == endIndex) {
childSubscriber.onCompleted();
return;
}
requestedAmount = get();
if (requestedAmount == emitted) {
currentIndex = index;
requestedAmount = addAndGet(-emitted);
if (requestedAmount == 0L) {
break;
}
emitted = 0L;
}
}
}
这里的childSubscriber是GroupBySubscriber,调用它的onNext
public void onNext(T t) {
if (done) {
return;
}
final Queue<GroupedObservable<K, V>> q = this.queue;
final Subscriber<? super GroupedObservable<K, V>> a = this.actual;
K key;
try {
key = keySelector.call(t);
} catch (Throwable ex) {
unsubscribe();
errorAll(a, q, ex);
return;
}
boolean notNew = true;
Object mapKey = key != null ? key : NULL_KEY;
GroupedUnicast<K, V> group = groups.get(mapKey);
if (group == null) {
// if the main has been cancelled, stop creating groups
// and skip this value
if (!cancelled.get()) {
group = GroupedUnicast.createWith(key, bufferSize, this, delayError);
groups.put(mapKey, group);
groupCount.getAndIncrement();
notNew = false;
q.offer(group);
drain();
} else {
return;
}
}
V v;
try {
v = valueSelector.call(t);
} catch (Throwable ex) {
unsubscribe();
errorAll(a, q, ex);
return;
}
group.onNext(v);
if (evictedKeys != null) {
K evictedKey;
while ((evictedKey = evictedKeys.poll()) != null) {
GroupedUnicast<K, V> g = groups.get(evictedKey);
if (g != null) {
g.onComplete();
}
}
}
if (notNew) {
s.request(1);
}
}
keySelector是我们代码中设置的分组依据
获取到当前key所属的组之后,判断当前是否已经添加过改组,没有则创建相应的GroupedUnicast添加到groups,并添加到队列
然后调用drain方法
void drain() {
if (wip.getAndIncrement() != 0) {
return;
}
int missed = 1;
final Queue<GroupedObservable<K, V>> q = this.queue;
final Subscriber<? super GroupedObservable<K, V>> a = this.actual;
for (;;) {
if (checkTerminated(done, q.isEmpty(), a, q)) {
return;
}
long r = requested.get();
long e = 0L;
while (e != r) {
boolean d = done;
GroupedObservable<K, V> t = q.poll();
boolean empty = t == null;
if (checkTerminated(d, empty, a, q)) {
return;
}
if (empty) {
break;
}
a.onNext(t);
e++;
}
if (e != 0L) {
if (r != Long.MAX_VALUE) {
BackpressureUtils.produced(requested, e);
}
s.request(e);
}
missed = wip.addAndGet(-missed);
if (missed == 0) {
break;
}
}
}
这里队列已经不为空
a.onNext(t)
这里最终会调用到我们的订阅者
回到前面onNext,接着调用
v = valueSelector.call(t);
这里查看是否会对值做变换,我们这里没有
接着调用
group.onNext(v);
public void onNext(T t) {
state.onNext(t);
}
public void onNext(T t) {
if (t == null) {
error = new NullPointerException();
done = true;
} else {
queue.offer(NotificationLite.next(t));
}
drain();
}
这里入队列,然后调用drain,最终会调用到我们为这个组添加的订阅者
然后看下demo中
stringIntegerGroupedObservable.subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
System.out.println(stringIntegerGroupedObservable.getKey() + "'member: " + integer);
}
});
这里最终会调用到OperatorGroupBy的State的call
public void call(Subscriber<? super T> s) {
if (once.compareAndSet(false, true)) {
s.add(this);
s.setProducer(this);
actual.lazySet(s);
drain();
} else {
s.onError(new IllegalStateException("Only one Subscriber allowed!"));
}
}
这里会设置actual,它在前面的drain方法中会使用到