user2511882
user2511882

Reputation: 9152

Combining two different observables

Have the following snippet:

 Log.d("#######", Thread.currentThread().getName());
    RxSearchView.queryTextChangeEvents(searchView)
            .debounce(400, TimeUnit.MILLISECONDS,Schedulers.newThread())
            .flatMap(new Func1<SearchViewQueryTextEvent, Observable<GifsData>>() {
                @Override
                public Observable<GifsData> call(SearchViewQueryTextEvent txtChangeEvt) {
                    return RestWebClient.get().getSearchedGifs(txtChangeEvt.queryText().toString(),"dcJmzC");
                }
            })
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<GifsData>() {
                @Override
                public void onCompleted() {
                    Log.d("#######","onCompleted searchGifs");
                }

                @Override
                public void onError(Throwable e) {
                    Log.d("#######",e.toString());
                }

                @Override
                public void onNext(GifsData gifsData) {
                   mainFragmentPresenterInterface.displaySearchedGifsList(gifsData);
                }
            });
}

No matter what i try i keep getting the following error:

java.lang.IllegalStateException: Must be called from the main thread. Was: Thread[RxNewThreadScheduler-2,5,main]

Probably have spend close to an hour on this..Haven't been able to figure out what is the issue. Even tried matching my snippet to the following link:

Combine RxTextView Observable and Retrofit Observable

No luck. Can someone point out what is wrong here?

Thanks.

Upvotes: 1

Views: 161

Answers (2)

marwinXXII
marwinXXII

Reputation: 1446

Operator debounce by default uses computation scheduler, you need to change it to main thread (because you work with UI only on main).

Next thing is to schedule network request to be executed on io scheduler. (we are using only one subscribeOn now).

And again observing results on main thread to inreact with UI.

RxSearchView.queryTextChangeEvents(searchView)
  .debounce(400, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
  .flatMap(new Func1<SearchViewQueryTextEvent, Observable<GifsData>>() {
    @Override
    public Observable<GifsData> call(SearchViewQueryTextEvent txtChangeEvt) {
      return RestWebClient.get()
        .getSearchedGifs(txtChangeEvt.queryText().toString(),"dcJmzC")
        .subscribeOn(Schedulers.io());
    }
  })
  .observeOn(AndroidSchedulers.mainThread())
  .subscribe(new Observer<GifsData>() {
    @Override
    public void onCompleted() {
      Log.d("#######","onCompleted searchGifs");
    }

    @Override
    public void onError(Throwable e) {
      Log.d("#######",e.toString());
    }

    @Override
    public void onNext(GifsData gifsData) {
      mainFragmentPresenterInterface.displaySearchedGifsList(gifsData);
    }
});

Upvotes: 0

Sagar Trehan
Sagar Trehan

Reputation: 2446

Reason of error: You are subscribing result on background thread and you are accessing View in stream on background thread. Here I have invoked RestWebClient.get().getSearchedGifs(txtChangeEvt.queryText().toString(),"dcJmzC").subscribeOn(Schedulers.newThread());on background scheduler .Please try this it will work for you:

RxSearchView.queryTextChangeEvents(mSearchView)
            .debounce(400, TimeUnit.MILLISECONDS)
            .flatMap(new Func1<SearchViewQueryTextEvent, Observable<String>>() {
                @Override
                public Observable<String> call(SearchViewQueryTextEvent txtChangeEvt) {
                    return Observable.just(txtChangeEvt.queryText().toString()).subscribeOn(AndroidSchedulers.mainThread());
                }
            })
            .flatMap(new Func1<GifsData, Observable<String>>() {
                @Override
                public Observable<GifsData> call(String txtChangeEvt) {
                    return RestWebClient.get().getSearchedGifs(txtChangeEvt,"dcJmzC").subscribeOn(Schedulers.newThread());
                }
            })
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<GifsData>() {
                @Override
                public void onCompleted() {
                    Log.d("#######","onCompleted searchGifs");
                }

                @Override
                public void onError(Throwable e) {
                    Log.d("#######",e.toString());
                }

                @Override
                public void onNext(GifsData gifsData) {
                    Log.d("#######", gifsData);
                }
            });

Let me know if it helps

Upvotes: 2

Related Questions