2016-09-18 95 views
8

当用户类型分为SearchView小部件,应用程序应该作出 API调用(在后台线程)从服务器获取搜索结果,并且(在UI线程)在RecyclerView显示它们。如何使用SearchView,Retrofit和RxJava(RxBindings)实现搜索功能?

我使用下面的代码在我的片段:

@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(...) 
        } 
       }); 
} 

但我得到一个异常:

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()),创建片段时,搜索API调用被触发,没有查询输入SearchView,我得到exeption

retrofit2.adapter.rxjava.HttpException: HTTP 422 

然后,当我输入我的搜索查询retrofitService.search(query)不再被调用。

回答

14

请记住,您实际上可以在您的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(...) 
       } 
      }); 

这基本上都会导致此主题用法:

thread usage

+2

否则,你可以在配置改造时指定IO线程 - .addCallAdapterFactory(RxJavaCallAdapterFactory.create(调度器.io)) – Outofdate

+0

是的,然后'.observeOn(Schedulers.io())'是不必要的 –

相关问题