我正在试验RxJava for Android。我尝试了一个简单的例子,我尝试在后台线程上卸载更长的操作,然后期望返回主线程并执行ui操作。
我从EditText
onTextChangeListener
(通过漂亮的ButterKnife注入)获取搜索文本,然后将其拍摄到长时间运行的操作_searchForContacts(searchText)
,该操作返回联系人列表对象。然后,我通过在适配器上设置信息并通知数据集更改来继续更新我的视图。
但是,在尝试进行任何ui更新时遇到异常,因为我从不在主线程上。
这是我的代码:
public class MyTestFragment
extends Fragment
implements Observer<List<Contact>> {
// ...
private Subscription _searchGuestsSubscription = Subscriptions.empty();
// ...
@Override
public void onDestroyView() {
super.onDestroyView();
_searchGuestsSubscription.unsubscribe();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
_adapter = new ContactImportAdapter();
_adapter.setContacts(_searchForContacts(ALL_CONTACTS));
_listView.setAdapter(_adapter);
}
@Override
public void onNext(List<Contact> contactSearchResults) {
Timber.d("I'm on the main thread -> " + String.valueOf(Looper.myLooper() == Looper.getMainLooper()));
_adapter.setContacts(contactSearchResults);
}
@Override
public void onCompleted() {
_updateView();
}
@Override
public void onError(Throwable e) {
Timber.e(e, "Oops something went wrong.");
}
// ButterKnife ~ onTextChangeListener
@OnTextChanged(R.id.search_edit_text)
void onSearchContact(CharSequence searchChars) {
_searchGuestsSubscription = AndroidObservable.bindFragment(this,
_searchGuestsObservable(searchChars.toString()))
// The below line doesn't seem to have any effect?
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(this);
}
private Observable<List<Contact>> _searchGuestsObservable(final String searchText) {
return Observable.create(new Observable.OnSubscribe<List<Contact>>() {
@Override
public void call(Subscriber<? super List<Contact>> searchResultObserver) {
// do the search
List<Contact> contactSearchResults = _searchForContacts(searchText);
onNext(contactSearchResults);
onCompleted();
}
});
}
private void _updateView() {
_adapter.notifyDataSetChanged();
}
}
它表示始终在后台线程上调用onNext
。我得到了通常的IllegalStateException: The current thread must have a looper!
例外。日志语句还表明我不在onNext
内的主线程上。
是什么给出了?
答案 0 :(得分:1)
您的问题似乎来自于您直接在Fragment中调用onNext而不是调用订阅者的onNext这一事实。
更改您的代码。
private Observable<List<Contact>> _searchGuestsObservable(final String searchText) {
return Observable.create(new Observable.OnSubscribe<List<Contact>>() {
@Override
public void call(Subscriber<? super List<Contact>> searchResultObserver) {
// do the search
List<Contact> contactSearchResults = _searchForContacts(searchText);
searchResultObserver.onNext(contactSearchResults);
searchResultObserver.onCompleted();
}
});
}
当你的Observable.OnSubscribe<List<Contact>>()
被执行时,你当然是在后台线程上因为subscribeOn(Schedulers.io())
并且你自己调用你的片段onNext,这就是你得到那个例外的原因。