Android RxJava takeuntil运算符引发IllegalStateException
我正在尝试使用RxJava实现一个简单的自动完成视图, 按下cancel(取消)按钮取消后端呼叫。 这是我的代码:Android RxJava takeuntil运算符引发IllegalStateException,android,rx-java,Android,Rx Java,我正在尝试使用RxJava实现一个简单的自动完成视图, 按下cancel(取消)按钮取消后端呼叫。 这是我的代码: Observable<String> searchButton$ = RxView .clicks(searchButton) .map(item -> mEditText.getText().to
Observable<String> searchButton$ = RxView
.clicks(searchButton)
.map(item -> mEditText.getText().toString());
Observable<Integer> cancelRequest$ = RxView
.clicks(cancelRequest)
.scan(0,(counter,string) -> ++counter)
.skip(1);
Observable<String> search$ = searchButton$
.distinctUntilChanged()
.debounce(1,TimeUnit.SECONDS)
.doOnNext(text-> {
Log.i(TAG,"Searching ["+text+"]");
});
search$
.observeOn(Schedulers.single())
.doOnError(error -> {
Log.d(TAG,"Error after ObserveOn");
error.printStackTrace();
})
.switchMap(text ->
fetchList(text)
.doOnError(error -> {
Log.d(TAG,"Error after FetchList");
error.printStackTrace();
})
.takeUntil(cancelRequest$)
.doOnError(error -> {
Log.d(TAG,"Error after TakeUntil");
error.printStackTrace();
})
)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(list -> {
Log.i(TAG,"Fetched:"+ list.toString());
resultView.setText("");
list.forEach(item -> resultView.append(item + "\n"));
});
我不明白为什么TakeTill希望在主线程上调用。
我尝试在takeUntil之前添加ObserveOn(AndroidSchedulers.mainThread()),但错误仍然是一样的
有什么想法吗 如果你在RxBinding代码中钻研一下,你就会找到答案
单击
定义:
/**
* Create an observable which emits on {@code view} click events. The emitted value is
* unspecified and should only be used as notification.
* <p>
* <em>Warning:</em> The created observable keeps a strong reference to {@code view}. Unsubscribe
* to free this reference.
* <p>
* <em>Warning:</em> The created observable uses {@link View#setOnClickListener} to observe
* clicks. Only one observable can be used for a view at a time.
*/
@CheckResult @NonNull
public static Observable<Object> clicks(@NonNull View view) {
checkNotNull(view, "view == null");
return new ViewClickObservable(view);
}
final class ViewClickObservable extends Observable<Object> {
private final View view;
ViewClickObservable(View view) {
this.view = view;
}
@Override protected void subscribeActual(Observer<? super Object> observer) {
if (!checkMainThread(observer)) {
return;
}
Listener listener = new Listener(view, observer);
observer.onSubscribe(listener);
view.setOnClickListener(listener);
}
static final class Listener extends MainThreadDisposable implements OnClickListener {
private final View view;
private final Observer<? super Object> observer;
Listener(View view, Observer<? super Object> observer) {
this.view = view;
this.observer = observer;
}
@Override public void onClick(View v) {
if (!isDisposed()) {
observer.onNext(Notification.INSTANCE);
}
}
@Override protected void onDispose() {
view.setOnClickListener(null);
}
}
}
public static boolean checkMainThread(Observer<?> observer) {
if (Looper.myLooper() != Looper.getMainLooper()) {
observer.onSubscribe(Disposables.empty());
observer.onError(new IllegalStateException(
"Expected to be called on the main thread but was " + Thread.currentThread().getName()));
return false;
}
return true;
}
在subscribebeactual
方法中,您会注意到!选中具有以下定义的主线程(观察者)
:
/**
* Create an observable which emits on {@code view} click events. The emitted value is
* unspecified and should only be used as notification.
* <p>
* <em>Warning:</em> The created observable keeps a strong reference to {@code view}. Unsubscribe
* to free this reference.
* <p>
* <em>Warning:</em> The created observable uses {@link View#setOnClickListener} to observe
* clicks. Only one observable can be used for a view at a time.
*/
@CheckResult @NonNull
public static Observable<Object> clicks(@NonNull View view) {
checkNotNull(view, "view == null");
return new ViewClickObservable(view);
}
final class ViewClickObservable extends Observable<Object> {
private final View view;
ViewClickObservable(View view) {
this.view = view;
}
@Override protected void subscribeActual(Observer<? super Object> observer) {
if (!checkMainThread(observer)) {
return;
}
Listener listener = new Listener(view, observer);
observer.onSubscribe(listener);
view.setOnClickListener(listener);
}
static final class Listener extends MainThreadDisposable implements OnClickListener {
private final View view;
private final Observer<? super Object> observer;
Listener(View view, Observer<? super Object> observer) {
this.view = view;
this.observer = observer;
}
@Override public void onClick(View v) {
if (!isDisposed()) {
observer.onNext(Notification.INSTANCE);
}
}
@Override protected void onDispose() {
view.setOnClickListener(null);
}
}
}
public static boolean checkMainThread(Observer<?> observer) {
if (Looper.myLooper() != Looper.getMainLooper()) {
observer.onSubscribe(Disposables.empty());
observer.onError(new IllegalStateException(
"Expected to be called on the main thread but was " + Thread.currentThread().getName()));
return false;
}
return true;
}
如果你在RxBinding代码中挖掘一点,你就会找到答案
单击
定义:
/**
* Create an observable which emits on {@code view} click events. The emitted value is
* unspecified and should only be used as notification.
* <p>
* <em>Warning:</em> The created observable keeps a strong reference to {@code view}. Unsubscribe
* to free this reference.
* <p>
* <em>Warning:</em> The created observable uses {@link View#setOnClickListener} to observe
* clicks. Only one observable can be used for a view at a time.
*/
@CheckResult @NonNull
public static Observable<Object> clicks(@NonNull View view) {
checkNotNull(view, "view == null");
return new ViewClickObservable(view);
}
final class ViewClickObservable extends Observable<Object> {
private final View view;
ViewClickObservable(View view) {
this.view = view;
}
@Override protected void subscribeActual(Observer<? super Object> observer) {
if (!checkMainThread(observer)) {
return;
}
Listener listener = new Listener(view, observer);
observer.onSubscribe(listener);
view.setOnClickListener(listener);
}
static final class Listener extends MainThreadDisposable implements OnClickListener {
private final View view;
private final Observer<? super Object> observer;
Listener(View view, Observer<? super Object> observer) {
this.view = view;
this.observer = observer;
}
@Override public void onClick(View v) {
if (!isDisposed()) {
observer.onNext(Notification.INSTANCE);
}
}
@Override protected void onDispose() {
view.setOnClickListener(null);
}
}
}
public static boolean checkMainThread(Observer<?> observer) {
if (Looper.myLooper() != Looper.getMainLooper()) {
observer.onSubscribe(Disposables.empty());
observer.onError(new IllegalStateException(
"Expected to be called on the main thread but was " + Thread.currentThread().getName()));
return false;
}
return true;
}
在subscribebeactual
方法中,您会注意到!选中具有以下定义的主线程(观察者)
:
/**
* Create an observable which emits on {@code view} click events. The emitted value is
* unspecified and should only be used as notification.
* <p>
* <em>Warning:</em> The created observable keeps a strong reference to {@code view}. Unsubscribe
* to free this reference.
* <p>
* <em>Warning:</em> The created observable uses {@link View#setOnClickListener} to observe
* clicks. Only one observable can be used for a view at a time.
*/
@CheckResult @NonNull
public static Observable<Object> clicks(@NonNull View view) {
checkNotNull(view, "view == null");
return new ViewClickObservable(view);
}
final class ViewClickObservable extends Observable<Object> {
private final View view;
ViewClickObservable(View view) {
this.view = view;
}
@Override protected void subscribeActual(Observer<? super Object> observer) {
if (!checkMainThread(observer)) {
return;
}
Listener listener = new Listener(view, observer);
observer.onSubscribe(listener);
view.setOnClickListener(listener);
}
static final class Listener extends MainThreadDisposable implements OnClickListener {
private final View view;
private final Observer<? super Object> observer;
Listener(View view, Observer<? super Object> observer) {
this.view = view;
this.observer = observer;
}
@Override public void onClick(View v) {
if (!isDisposed()) {
observer.onNext(Notification.INSTANCE);
}
}
@Override protected void onDispose() {
view.setOnClickListener(null);
}
}
}
public static boolean checkMainThread(Observer<?> observer) {
if (Looper.myLooper() != Looper.getMainLooper()) {
observer.onSubscribe(Disposables.empty());
observer.onError(new IllegalStateException(
"Expected to be called on the main thread but was " + Thread.currentThread().getName()));
return false;
}
return true;
}
没有stacktrace,我们就无法暗示可能出错的地方。没有stacktrace,我们就无法暗示可能出错的地方。