forked from ReactiveX/RxJava
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSubject.java
More file actions
126 lines (107 loc) · 4.57 KB
/
Copy pathSubject.java
File metadata and controls
126 lines (107 loc) · 4.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package rx.subjects;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import junit.framework.Assert;
import org.junit.Test;
import rx.Notification;
import rx.Observable;
import rx.Observer;
import rx.Subscription;
import rx.util.AtomicObservableSubscription;
import rx.util.SynchronizedObserver;
import rx.util.functions.Action1;
import rx.util.functions.Func1;
public class Subject<T> extends Observable<T> implements Observer<T> {
public static <T> Subject<T> create() {
final ConcurrentHashMap<Subscription, Observer<T>> observers = new ConcurrentHashMap<Subscription, Observer<T>>();
Func1<Observer<T>, Subscription> onSubscribe = new Func1<Observer<T>, Subscription>() {
@Override
public Subscription call(Observer<T> observer) {
final AtomicObservableSubscription subscription = new AtomicObservableSubscription();
subscription.wrap(new Subscription() {
@Override
public void unsubscribe() {
// on unsubscribe remove it from the map of outbound observers to notify
observers.remove(subscription);
}
});
// on subscribe add it to the map of outbound observers to notify
observers.put(subscription, new SynchronizedObserver<T>(observer, subscription));
return subscription;
}
};
return new Subject<T>(onSubscribe, observers);
}
private final ConcurrentHashMap<Subscription, Observer<T>> observers;
protected Subject(Func1<Observer<T>, Subscription> onSubscribe, ConcurrentHashMap<Subscription, Observer<T>> observers) {
super(onSubscribe);
this.observers = observers;
}
@Override
public void onCompleted() {
for (Observer<T> observer : observers.values()) {
observer.onCompleted();
}
}
@Override
public void onError(Exception e) {
for (Observer<T> observer : observers.values()) {
observer.onError(e);
}
}
@Override
public void onNext(T args) {
for (Observer<T> observer : observers.values()) {
observer.onNext(args);
}
}
public static class UnitTest {
@Test
public void test() {
Subject<Integer> subject = Subject.create();
final AtomicReference<List<Notification<String>>> actualRef = new AtomicReference<List<Notification<String>>>();
Observable<List<Notification<Integer>>> wNotificationsList = subject.materialize().toList();
wNotificationsList.subscribe(new Action1<List<Notification<String>>>() {
@Override
public void call(List<Notification<String>> actual) {
actualRef.set(actual);
}
});
Subscription sub = Observable.create(new Func1<Observer<Integer>, Subscription>() {
@Override
public Subscription call(final Observer<Integer> observer) {
final AtomicBoolean stop = new AtomicBoolean(false);
new Thread() {
@Override
public void run() {
int i = 1;
while (!stop.get()) {
observer.onNext(i++);
}
observer.onCompleted();
}
}.start();
return new Subscription() {
@Override
public void unsubscribe() {
stop.set(true);
}
};
}
}).subscribe(subject);
// the subject has received an onComplete from the first subscribe because
// it is synchronous and the next subscribe won't do anything.
Observable.toObservable(-1, -2, -3).subscribe(subject);
List<Notification<Integer>> expected = new ArrayList<Notification<Integer>>();
expected.add(new Notification<Integer>(-1));
expected.add(new Notification<Integer>(-2));
expected.add(new Notification<Integer>(-3));
expected.add(new Notification<Integer>());
Assert.assertTrue(actualRef.get().containsAll(expected));
sub.unsubscribe();
}
}
}