Skip to content

Commit cec2bfd

Browse files
Merge pull request #880 from zsxwing/android-unsubscribe-thread-safe
Force ViewObservable be subscribed and unsubscribed in the UI thread
2 parents a7a0ee9 + f98616d commit cec2bfd

File tree

5 files changed

+56
-5
lines changed

5 files changed

+56
-5
lines changed

rxjava-contrib/rxjava-android/src/main/java/rx/android/observables/ViewObservable.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package rx.android.observables;
1717

18+
import android.os.Looper;
1819
import android.view.View;
1920
import android.widget.CompoundButton;
2021
import android.widget.EditText;
@@ -37,5 +38,10 @@ public static Observable<Boolean> input(final CompoundButton button, final boole
3738
return Observable.create(new OperatorCompoundButtonInput(button, emitInitialValue));
3839
}
3940

41+
public static void assertUiThread() {
42+
if (Looper.getMainLooper() != Looper.myLooper()) {
43+
throw new IllegalStateException("Observers must subscribe from the main UI thread, but was " + Thread.currentThread());
44+
}
45+
}
4046
}
4147

rxjava-contrib/rxjava-android/src/main/java/rx/operators/OperationObserveFromAndroidComponent.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818
import rx.Observable;
1919
import rx.Observer;
2020
import rx.Subscription;
21+
import rx.Scheduler.Inner;
2122
import rx.android.schedulers.AndroidSchedulers;
2223
import rx.subscriptions.Subscriptions;
2324
import rx.util.functions.Action0;
25+
import rx.util.functions.Action1;
2426
import android.app.Activity;
2527
import android.os.Looper;
2628
import android.util.Log;
@@ -100,8 +102,15 @@ public void onNext(T args) {
100102
@Override
101103
public void call() {
102104
log("unsubscribing from source sequence");
103-
releaseReferences();
104-
sourceSub.unsubscribe();
105+
AndroidSchedulers.mainThread().schedule(new Action1<Inner>() {
106+
107+
@Override
108+
public void call(Inner t1) {
109+
releaseReferences();
110+
sourceSub.unsubscribe();
111+
}
112+
113+
});
105114
}
106115
});
107116
}

rxjava-contrib/rxjava-android/src/main/java/rx/operators/OperatorCompoundButtonInput.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,12 @@
2323
import rx.Observable;
2424
import rx.Subscriber;
2525
import rx.Subscription;
26+
import rx.Scheduler.Inner;
27+
import rx.android.observables.ViewObservable;
28+
import rx.android.schedulers.AndroidSchedulers;
2629
import rx.subscriptions.Subscriptions;
2730
import rx.util.functions.Action0;
31+
import rx.util.functions.Action1;
2832
import android.view.View;
2933
import android.widget.CompoundButton;
3034

@@ -39,6 +43,7 @@ public OperatorCompoundButtonInput(final CompoundButton button, final boolean em
3943

4044
@Override
4145
public void call(final Subscriber<? super Boolean> observer) {
46+
ViewObservable.assertUiThread();
4247
final CompositeOnCheckedChangeListener composite = CachedListeners.getFromViewOrCreate(button);
4348

4449
final CompoundButton.OnCheckedChangeListener listener = new CompoundButton.OnCheckedChangeListener() {
@@ -51,7 +56,14 @@ public void onCheckedChanged(final CompoundButton button, final boolean checked)
5156
final Subscription subscription = Subscriptions.create(new Action0() {
5257
@Override
5358
public void call() {
54-
composite.removeOnCheckedChangeListener(listener);
59+
AndroidSchedulers.mainThread().schedule(new Action1<Inner>() {
60+
61+
@Override
62+
public void call(Inner t1) {
63+
composite.removeOnCheckedChangeListener(listener);
64+
}
65+
66+
});
5567
}
5668
});
5769

rxjava-contrib/rxjava-android/src/main/java/rx/operators/OperatorEditTextInput.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@
1818
import rx.Observable;
1919
import rx.Subscriber;
2020
import rx.Subscription;
21+
import rx.Scheduler.Inner;
22+
import rx.android.observables.ViewObservable;
23+
import rx.android.schedulers.AndroidSchedulers;
2124
import rx.subscriptions.Subscriptions;
2225
import rx.util.functions.Action0;
26+
import rx.util.functions.Action1;
2327
import android.text.Editable;
2428
import android.text.TextWatcher;
2529
import android.widget.EditText;
@@ -35,6 +39,7 @@ public OperatorEditTextInput(final EditText input, final boolean emitInitialValu
3539

3640
@Override
3741
public void call(final Subscriber<? super String> observer) {
42+
ViewObservable.assertUiThread();
3843
final TextWatcher watcher = new SimpleTextWatcher() {
3944
@Override
4045
public void afterTextChanged(final Editable editable) {
@@ -45,7 +50,14 @@ public void afterTextChanged(final Editable editable) {
4550
final Subscription subscription = Subscriptions.create(new Action0() {
4651
@Override
4752
public void call() {
48-
input.removeTextChangedListener(watcher);
53+
AndroidSchedulers.mainThread().schedule(new Action1<Inner>() {
54+
55+
@Override
56+
public void call(Inner t1) {
57+
input.removeTextChangedListener(watcher);
58+
}
59+
60+
});
4961
}
5062
});
5163

rxjava-contrib/rxjava-android/src/main/java/rx/operators/OperatorViewClick.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,14 @@
2121
import java.util.WeakHashMap;
2222

2323
import rx.Observable;
24+
import rx.Scheduler.Inner;
2425
import rx.Subscriber;
2526
import rx.Subscription;
27+
import rx.android.observables.ViewObservable;
28+
import rx.android.schedulers.AndroidSchedulers;
2629
import rx.subscriptions.Subscriptions;
2730
import rx.util.functions.Action0;
31+
import rx.util.functions.Action1;
2832
import android.view.View;
2933

3034
public final class OperatorViewClick implements Observable.OnSubscribe<View> {
@@ -38,6 +42,7 @@ public OperatorViewClick(final View view, final boolean emitInitialValue) {
3842

3943
@Override
4044
public void call(final Subscriber<? super View> observer) {
45+
ViewObservable.assertUiThread();
4146
final CompositeOnClickListener composite = CachedListeners.getFromViewOrCreate(view);
4247

4348
final View.OnClickListener listener = new View.OnClickListener() {
@@ -50,7 +55,14 @@ public void onClick(final View clicked) {
5055
final Subscription subscription = Subscriptions.create(new Action0() {
5156
@Override
5257
public void call() {
53-
composite.removeOnClickListener(listener);
58+
AndroidSchedulers.mainThread().schedule(new Action1<Inner>() {
59+
60+
@Override
61+
public void call(Inner t1) {
62+
composite.removeOnClickListener(listener);
63+
}
64+
65+
});
5466
}
5567
});
5668

0 commit comments

Comments
 (0)