当用户在 SearchView
小部件中输入内容时,应用程序应该制作一个
API 调用(在后台线程中)从服务器获取搜索结果,并在 RecyclerView 中显示它们(在 UI 线程中)。
我在 fragment 中使用了以下代码:
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.my_fragment, menu);
SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));
RxSearchView.queryTextChanges(searchView)
.debounce(400, TimeUnit.MILLISECONDS)
.map(CharSequence::toString)
.switchMap(query -> retrofitService.search(query))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<Item>>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
Log.e(LOG_TAG, "Error", e);
}
@Override
public void onNext(List<Item> items) {
// adapter.addItems(...)
}
});
}
但我得到一个异常(exception):
java.lang.IllegalStateException: Must be called from the main thread. Was: Thread[RxIoScheduler-2,5,main]
at com.jakewharton.rxbinding.internal.Preconditions.checkUiThread(Preconditions.java:35)
at com.jakewharton.rxbinding.support.v7.widget.SearchViewQueryTextChangesOnSubscribe.call(SearchViewQueryTextChangesOnSubscribe.java:18)
at com.jakewharton.rxbinding.support.v7.widget.SearchViewQueryTextChangesOnSubscribe.call(SearchViewQueryTextChangesOnSubscribe.java:10)
...
当我删除 .subscribeOn(Schedulers.io())
时,会在创建 fragment 且未在 SearchView
中键入任何查询时触发搜索 API 调用,我得到异常
retrofit2.adapter.rxjava.HttpException: HTTP 422
然后,当我输入搜索查询时,retrofitService.search(query)
不再被调用。
最佳答案
请记住,您实际上可以在 rx 链中使用多个 observeOn
和多个 subscribeOn
运算符。
试试这个:
RxSearchView.queryTextChanges(searchView)
.debounce(400, TimeUnit.MILLISECONDS)
.map(CharSequence::toString)
.subscribeOn(AndroidSchedulers.mainThread())
.observeOn(Schedulers.io())
.switchMap(query -> retrofitService.search(query))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<Item>>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
Log.e(LOG_TAG, "Error", e);
}
@Override
public void onNext(List<Item> items) {
// adapter.addItems(...)
}
});
这基本上会导致线程使用:
关于java - 如何使用 SearchView、Retrofit 和 RxJava (RxBindings) 实现搜索功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39558885/