77
77
import rx .plugins .RxJavaErrorHandler ;
78
78
import rx .plugins .RxJavaObservableExecutionHook ;
79
79
import rx .plugins .RxJavaPlugins ;
80
+ import rx .subjects .PublishSubject ;
80
81
import rx .subjects .Subject ;
81
82
import rx .subscriptions .BooleanSubscription ;
82
83
import rx .subscriptions .Subscriptions ;
@@ -1665,6 +1666,17 @@ public static <T> Observable<T> onErrorReturn(final Observable<T> that, Func1<Ex
1665
1666
return create (OperationOnErrorReturn .onErrorReturn (that , resumeFunction ));
1666
1667
}
1667
1668
1669
+ /**
1670
+ * Returns a connectable observable sequence that shares a single subscription to the underlying sequence.
1671
+ *
1672
+ * @param that
1673
+ * the source Observable
1674
+ * @return a connectable observable sequence that upon connection causes the source sequence to push results into the specified subject.
1675
+ */
1676
+ public static <T > ConnectableObservable <T > publish (final Observable <T > that ) {
1677
+ return OperationMulticast .multicast (that , PublishSubject .<T > create ());
1678
+ }
1679
+
1668
1680
/**
1669
1681
* Returns an Observable that applies a function of your choosing to the first item emitted by a
1670
1682
* source Observable, then feeds the result of that function along with the second item emitted
@@ -1720,7 +1732,7 @@ public T call(T t1, T t2) {
1720
1732
public static <T > Observable <T > aggregate (Observable <T > sequence , Func2 <T , T , T > accumulator ) {
1721
1733
return reduce (sequence , accumulator );
1722
1734
}
1723
-
1735
+
1724
1736
/**
1725
1737
* Used by dynamic languages.
1726
1738
*
@@ -1729,7 +1741,7 @@ public static <T> Observable<T> aggregate(Observable<T> sequence, Func2<T, T, T>
1729
1741
public static <T > Observable <T > aggregate (Observable <T > sequence , Object accumulator ) {
1730
1742
return reduce (sequence , accumulator );
1731
1743
}
1732
-
1744
+
1733
1745
/**
1734
1746
* Returns an Observable that applies a function of your choosing to the first item emitted by a
1735
1747
* source Observable, then feeds the result of that function along with the second item emitted
@@ -1787,7 +1799,7 @@ public R call(R r, T t) {
1787
1799
public static <T , R > Observable <R > aggregate (Observable <T > sequence , R initialValue , Func2 <R , T , R > accumulator ) {
1788
1800
return reduce (sequence , initialValue , accumulator );
1789
1801
}
1790
-
1802
+
1791
1803
/**
1792
1804
* Used by dynamic languages.
1793
1805
*
@@ -1796,7 +1808,7 @@ public static <T, R> Observable<R> aggregate(Observable<T> sequence, R initialVa
1796
1808
public static <T , R > Observable <R > aggregate (Observable <T > sequence , R initialValue , Object accumulator ) {
1797
1809
return reduce (sequence , initialValue , accumulator );
1798
1810
}
1799
-
1811
+
1800
1812
/**
1801
1813
* Returns an Observable that applies a function of your choosing to the first item emitted by a
1802
1814
* source Observable, then feeds the result of that function along with the second item emitted
@@ -2003,7 +2015,7 @@ public static <T> Observable<T> takeLast(final Observable<T> items, final int co
2003
2015
* @param items
2004
2016
* @param predicate
2005
2017
* a function to test each source element for a condition
2006
- * @return the values from the start of the given sequence
2018
+ * @return the values from the start of the given sequence
2007
2019
*/
2008
2020
public static <T > Observable <T > takeWhile (final Observable <T > items , Func1 <T , Boolean > predicate ) {
2009
2021
return create (OperationTakeWhile .takeWhile (items , predicate ));
@@ -2015,7 +2027,7 @@ public static <T> Observable<T> takeWhile(final Observable<T> items, Func1<T, Bo
2015
2027
* @param items
2016
2028
* @param predicate
2017
2029
* a function to test each source element for a condition
2018
- * @return the values from the start of the given sequence
2030
+ * @return the values from the start of the given sequence
2019
2031
*/
2020
2032
public static <T > Observable <T > takeWhile (final Observable <T > items , Object predicate ) {
2021
2033
@ SuppressWarnings ("rawtypes" )
@@ -2035,7 +2047,7 @@ public Boolean call(T t) {
2035
2047
* @param items
2036
2048
* @param predicate
2037
2049
* a function to test each element for a condition; the second parameter of the function represents the index of the source element; otherwise, false.
2038
- * @return the values from the start of the given sequence
2050
+ * @return the values from the start of the given sequence
2039
2051
*/
2040
2052
public static <T > Observable <T > takeWhileWithIndex (final Observable <T > items , Func2 <T , Integer , Boolean > predicate ) {
2041
2053
return create (OperationTakeWhile .takeWhileWithIndex (items , predicate ));
@@ -2057,12 +2069,13 @@ public Boolean call(T t, Integer integer)
2057
2069
2058
2070
/**
2059
2071
* Adds a timestamp to each item emitted by this observable.
2072
+ *
2060
2073
* @return An observable sequence of timestamped items.
2061
2074
*/
2062
2075
public Observable <Timestamped <T >> timestamp () {
2063
2076
return create (OperationTimestamp .timestamp (this ));
2064
2077
}
2065
-
2078
+
2066
2079
/**
2067
2080
* Return a Future representing a single value of the Observable.
2068
2081
* <p>
@@ -2384,7 +2397,7 @@ public static <T> Observable<T> toObservable(T... items) {
2384
2397
* @param sequence
2385
2398
* @throws ClassCastException
2386
2399
* if T objects do not implement Comparable
2387
- * @return an observable containing the sorted list
2400
+ * @return an observable containing the sorted list
2388
2401
*/
2389
2402
public static <T > Observable <List <T >> toSortedList (Observable <T > sequence ) {
2390
2403
return create (OperationToObservableSortedList .toSortedList (sequence ));
@@ -2397,7 +2410,7 @@ public static <T> Observable<List<T>> toSortedList(Observable<T> sequence) {
2397
2410
*
2398
2411
* @param sequence
2399
2412
* @param sortFunction
2400
- * @return an observable containing the sorted list
2413
+ * @return an observable containing the sorted list
2401
2414
*/
2402
2415
public static <T > Observable <List <T >> toSortedList (Observable <T > sequence , Func2 <T , T , Integer > sortFunction ) {
2403
2416
return create (OperationToObservableSortedList .toSortedList (sequence , sortFunction ));
@@ -2410,7 +2423,7 @@ public static <T> Observable<List<T>> toSortedList(Observable<T> sequence, Func2
2410
2423
*
2411
2424
* @param sequence
2412
2425
* @param sortFunction
2413
- * @return an observable containing the sorted list
2426
+ * @return an observable containing the sorted list
2414
2427
*/
2415
2428
public static <T > Observable <List <T >> toSortedList (Observable <T > sequence , final Object sortFunction ) {
2416
2429
@ SuppressWarnings ("rawtypes" )
@@ -3186,6 +3199,15 @@ public Observable<T> reduce(Func2<T, T, T> accumulator) {
3186
3199
return reduce (this , accumulator );
3187
3200
}
3188
3201
3202
+ /**
3203
+ * Returns a connectable observable sequence that shares a single subscription to the underlying sequence.
3204
+ *
3205
+ * @return a connectable observable sequence that upon connection causes the source sequence to push results into the specified subject.
3206
+ */
3207
+ public ConnectableObservable <T > publish () {
3208
+ return OperationMulticast .multicast (this , PublishSubject .<T > create ());
3209
+ }
3210
+
3189
3211
/**
3190
3212
* Used by dynamic languages.
3191
3213
*
@@ -3201,7 +3223,7 @@ public Observable<T> reduce(Object accumulator) {
3201
3223
public Observable <T > aggregate (Func2 <T , T , T > accumulator ) {
3202
3224
return aggregate (this , accumulator );
3203
3225
}
3204
-
3226
+
3205
3227
/**
3206
3228
* Used by dynamic languages.
3207
3229
*
@@ -3210,7 +3232,7 @@ public Observable<T> aggregate(Func2<T, T, T> accumulator) {
3210
3232
public Observable <T > aggregate (Object accumulator ) {
3211
3233
return aggregate (this , accumulator );
3212
3234
}
3213
-
3235
+
3214
3236
/**
3215
3237
* Returns an Observable that applies a function of your choosing to the first item emitted by a
3216
3238
* source Observable, then feeds the result of that function along with the second item emitted
@@ -3263,7 +3285,7 @@ public <R> Observable<R> aggregate(R initialValue, Func2<R, T, R> accumulator) {
3263
3285
public <R > Observable <R > aggregate (R initialValue , Object accumulator ) {
3264
3286
return aggregate (this , initialValue , accumulator );
3265
3287
}
3266
-
3288
+
3267
3289
/**
3268
3290
* Returns an Observable that applies a function of your choosing to the first item emitted by a
3269
3291
* source Observable, then feeds the result of that function along with the second item emitted
@@ -3298,7 +3320,7 @@ public Observable<T> scan(Func2<T, T, T> accumulator) {
3298
3320
public Observable <T > sample (long period , TimeUnit unit ) {
3299
3321
return create (OperationSample .sample (this , period , unit ));
3300
3322
}
3301
-
3323
+
3302
3324
/**
3303
3325
* Samples the observable sequence at each interval.
3304
3326
*
@@ -3313,10 +3335,10 @@ public Observable<T> sample(long period, TimeUnit unit) {
3313
3335
public Observable <T > sample (long period , TimeUnit unit , Scheduler scheduler ) {
3314
3336
return create (OperationSample .sample (this , period , unit , scheduler ));
3315
3337
}
3316
-
3338
+
3317
3339
/**
3318
3340
* Used by dynamic languages.
3319
- *
3341
+ *
3320
3342
* @see #scan(Func2)
3321
3343
*/
3322
3344
public Observable <T > scan (final Object accumulator ) {
@@ -3348,7 +3370,7 @@ public <R> Observable<R> scan(R initialValue, Func2<R, T, R> accumulator) {
3348
3370
3349
3371
/**
3350
3372
* Used by dynamic languages.
3351
- *
3373
+ *
3352
3374
* @see #scan(Object, Func2)
3353
3375
*/
3354
3376
public <R > Observable <R > scan (final R initialValue , final Object accumulator ) {
@@ -3419,7 +3441,7 @@ public Observable<T> take(final int num) {
3419
3441
*
3420
3442
* @param predicate
3421
3443
* a function to test each source element for a condition
3422
- * @return the values from the start of the given sequence
3444
+ * @return the values from the start of the given sequence
3423
3445
*/
3424
3446
public Observable <T > takeWhile (final Func1 <T , Boolean > predicate ) {
3425
3447
return takeWhile (this , predicate );
@@ -3430,7 +3452,7 @@ public Observable<T> takeWhile(final Func1<T, Boolean> predicate) {
3430
3452
*
3431
3453
* @param predicate
3432
3454
* a function to test each source element for a condition
3433
- * @return the values from the start of the given sequence
3455
+ * @return the values from the start of the given sequence
3434
3456
*/
3435
3457
public Observable <T > takeWhile (final Object predicate ) {
3436
3458
return takeWhile (this , predicate );
@@ -3441,7 +3463,7 @@ public Observable<T> takeWhile(final Object predicate) {
3441
3463
*
3442
3464
* @param predicate
3443
3465
* a function to test each element for a condition; the second parameter of the function represents the index of the source element; otherwise, false.
3444
- * @return the values from the start of the given sequence
3466
+ * @return the values from the start of the given sequence
3445
3467
*/
3446
3468
public Observable <T > takeWhileWithIndex (final Func2 <T , Integer , Boolean > predicate ) {
3447
3469
return takeWhileWithIndex (this , predicate );
@@ -3452,7 +3474,7 @@ public Observable<T> takeWhileWithIndex(final Func2<T, Integer, Boolean> predica
3452
3474
*
3453
3475
* @param predicate
3454
3476
* a function to test each element for a condition; the second parameter of the function represents the index of the source element; otherwise, false.
3455
- * @return the values from the start of the given sequence
3477
+ * @return the values from the start of the given sequence
3456
3478
*/
3457
3479
public Observable <T > takeWhileWithIndex (final Object predicate ) {
3458
3480
return takeWhileWithIndex (this , predicate );
@@ -3523,7 +3545,7 @@ public Observable<List<T>> toList() {
3523
3545
*
3524
3546
* @throws ClassCastException
3525
3547
* if T objects do not implement Comparable
3526
- * @return an observable containing the sorted list
3548
+ * @return an observable containing the sorted list
3527
3549
*/
3528
3550
public Observable <List <T >> toSortedList () {
3529
3551
return toSortedList (this );
@@ -3535,7 +3557,7 @@ public Observable<List<T>> toSortedList() {
3535
3557
* <img width="640" src="https://raw.github.com/wiki/Netflix/RxJava/images/rx-operators/toSortedList.png">
3536
3558
*
3537
3559
* @param sortFunction
3538
- * @return an observable containing the sorted list
3560
+ * @return an observable containing the sorted list
3539
3561
*/
3540
3562
public Observable <List <T >> toSortedList (Func2 <T , T , Integer > sortFunction ) {
3541
3563
return toSortedList (this , sortFunction );
@@ -3547,7 +3569,7 @@ public Observable<List<T>> toSortedList(Func2<T, T, Integer> sortFunction) {
3547
3569
* <img width="640" src="https://raw.github.com/wiki/Netflix/RxJava/images/rx-operators/toSortedList.png">
3548
3570
*
3549
3571
* @param sortFunction
3550
- * @return an observable containing the sorted list
3572
+ * @return an observable containing the sorted list
3551
3573
*/
3552
3574
public Observable <List <T >> toSortedList (final Object sortFunction ) {
3553
3575
return toSortedList (this , sortFunction );
@@ -4140,6 +4162,63 @@ public void call(String t1) {
4140
4162
}
4141
4163
}
4142
4164
4165
+ @ Test
4166
+ public void testPublish () throws InterruptedException {
4167
+ final AtomicInteger counter = new AtomicInteger ();
4168
+ ConnectableObservable <String > o = Observable .create (new Func1 <Observer <String >, Subscription >() {
4169
+
4170
+ @ Override
4171
+ public Subscription call (final Observer <String > observer ) {
4172
+ final BooleanSubscription subscription = new BooleanSubscription ();
4173
+ new Thread (new Runnable () {
4174
+
4175
+ @ Override
4176
+ public void run () {
4177
+ System .out .println ("published observable being executed" );
4178
+ observer .onNext ("one" );
4179
+ observer .onCompleted ();
4180
+ counter .incrementAndGet ();
4181
+ }
4182
+ }).start ();
4183
+ return subscription ;
4184
+ }
4185
+ }).publish ();
4186
+
4187
+ final CountDownLatch latch = new CountDownLatch (2 );
4188
+
4189
+ // subscribe once
4190
+ o .subscribe (new Action1 <String >() {
4191
+
4192
+ @ Override
4193
+ public void call (String v ) {
4194
+ assertEquals ("one" , v );
4195
+ System .out .println ("v: " + v );
4196
+ latch .countDown ();
4197
+ }
4198
+ });
4199
+
4200
+ // subscribe again
4201
+ o .subscribe (new Action1 <String >() {
4202
+
4203
+ @ Override
4204
+ public void call (String v ) {
4205
+ assertEquals ("one" , v );
4206
+ System .out .println ("v: " + v );
4207
+ latch .countDown ();
4208
+ }
4209
+ });
4210
+
4211
+ Subscription s = o .connect ();
4212
+ try {
4213
+ if (!latch .await (1000 , TimeUnit .MILLISECONDS )) {
4214
+ fail ("subscriptions did not receive values" );
4215
+ }
4216
+ assertEquals (1 , counter .get ());
4217
+ } finally {
4218
+ s .unsubscribe ();
4219
+ }
4220
+ }
4221
+
4143
4222
private static class TestException extends RuntimeException {
4144
4223
private static final long serialVersionUID = 1L ;
4145
4224
}
0 commit comments