24
24
25
25
import android .app .Activity ;
26
26
import android .app .Fragment ;
27
+ import android .os .Looper ;
27
28
import android .util .Log ;
28
29
29
30
import java .lang .reflect .Field ;
31
+ import java .util .concurrent .Callable ;
32
+ import java .util .concurrent .Executors ;
33
+ import java .util .concurrent .Future ;
34
+ import java .util .concurrent .TimeUnit ;
30
35
31
36
public class OperationObserveFromAndroidComponent {
32
37
@@ -47,8 +52,8 @@ private static abstract class OnSubscribeBase<T, AndroidComponent> implements Ob
47
52
private static final String LOG_TAG = OperationObserveFromAndroidComponent .class .getSimpleName ();
48
53
49
54
private final Observable <T > source ;
50
- private volatile AndroidComponent componentRef ;
51
- private volatile Observer <? super T > observerRef ;
55
+ private AndroidComponent componentRef ;
56
+ private Observer <? super T > observerRef ;
52
57
53
58
private OnSubscribeBase (Observable <T > source , AndroidComponent component ) {
54
59
this .source = source ;
@@ -65,6 +70,7 @@ private void log(String message) {
65
70
66
71
@ Override
67
72
public Subscription onSubscribe (Observer <? super T > observer ) {
73
+ assertUiThread ();
68
74
observerRef = observer ;
69
75
final Subscription sourceSub = source .observeOn (AndroidSchedulers .mainThread ()).subscribe (new Observer <T >() {
70
76
@ Override
@@ -111,6 +117,12 @@ private void releaseReferences() {
111
117
observerRef = null ;
112
118
componentRef = null ;
113
119
}
120
+
121
+ private void assertUiThread () {
122
+ if (Looper .getMainLooper () != Looper .myLooper ()) {
123
+ throw new IllegalStateException ("Observers must subscribe from the main UI thread, but was " + Thread .currentThread ());
124
+ }
125
+ }
114
126
}
115
127
116
128
private static final class OnSubscribeFragment <T > extends OnSubscribeBase <T , android .app .Fragment > {
@@ -171,6 +183,21 @@ public void setupMocks() {
171
183
when (mockFragment .isAdded ()).thenReturn (true );
172
184
}
173
185
186
+ @ Test
187
+ public void itThrowsIfObserverSubscribesFromBackgroundThread () throws Exception {
188
+ final Future <Object > future = Executors .newSingleThreadExecutor ().submit (new Callable <Object >() {
189
+ @ Override
190
+ public Object call () throws Exception {
191
+ OperationObserveFromAndroidComponent .observeFromAndroidComponent (
192
+ mockObservable , mockFragment ).subscribe (mockObserver );
193
+ return null ;
194
+ }
195
+ });
196
+ future .get (1 , TimeUnit .SECONDS );
197
+ verify (mockObserver ).onError (any (IllegalStateException .class ));
198
+ verifyNoMoreInteractions (mockObserver );
199
+ }
200
+
174
201
@ Test
175
202
public void itObservesTheSourceSequenceOnTheMainUIThread () {
176
203
OperationObserveFromAndroidComponent .observeFromAndroidComponent (mockObservable , mockFragment ).subscribe (mockObserver );
0 commit comments