2017-10-04 10 views
1

新しいスレッドでRxJava監視オブジェクトを実行する際に問題が発生しています。 Scheduler.io()でジップDBクエリを実行しようとしていますが、UIスレッドは関係なくブロックします。理由は分かりません。 DB用UIスレッドで監視可能な状態になっています

コード:

public Observable<List<T>> searchModelsInView(View view, final Collection<String> searchTerms, 
     KeyMatchLevel keyMatchLevel, int queryLim) { 
    return Observable.just(
      searchModelsTask(view, new HashSet<>(searchTerms), keyMatchLevel, queryLim)); 
} 

ここでビュンと問題が発生したコードです:

public Observable<Set<Airport>> getSearchResultsForAll(String term, int queryLim) { 
    List<String> terms = CollectionsUtil.asArrayList(term); 
    Observable<List<Airport>> macObservable = onNewThread(
      searchModelsInView(getMacView(), terms, 
        KeyMatchLevel.PREFIXED, queryLim)); 
    Observable<List<Airport>> nameObservable = onNewThread(
      searchModelsInView(getNameView(), terms, 
        KeyMatchLevel.PREFIXED, queryLim)); 
    Observable<List<Airport>> codeObservable = onNewThread(
      searchModelsInView(getCodeView(), terms, 
        KeyMatchLevel.PREFIXED, NONE)); 
    Observable<List<Airport>> regionObservable = onNewThread(
      searchModelsInView(getCityView(), terms, 
        KeyMatchLevel.PREFIXED, NONE)); 

    ; 
    return Observable.zip(macObservable, nameObservable, codeObservable, regionObservable, 
      (macList, nameList, codeList, regionList) -> { 

       Set<Airport> resultSet = new LinkedHashSet<Airport>(); 

       Airport mac = macList.get(0); 

       if (term.length() > CODE_LEN) { 
        if (lowerCase(mac.getCity()).contains(lowerCase(term))) { 
         handleMACFound(resultSet, mac, regionList); 
         return resultSet; 
        } 
        resultSet.addAll(nameList); 
        resultSet.addAll(regionList); 
        return resultSet; 
       } 


       boolean macFound = StringUtil.isEquals(lowerCase(term), 
         lowerCase(mac.getCode())); 

       if (macFound) { 
        handleMACFound(resultSet, mac, codeList); 
        return resultSet; 
       } 

       resultSet.addAll(codeList); 
       resultSet.addAll(nameList); 
       resultSet.addAll(regionList); 

       return resultSet; 
      }); 
} 

private Observable<List<Airport>> onNewThread(Observable<List<Airport>> observable) { 
    return observable.subscribeOn(Schedulers.io()); 
} 

それが呼ばれています場所です:

public void searchKey(String searchTerms, Airport... excluding) { 
    TBDataBase.getAirportDB() 
      .getSearchResultsForAll(searchTerms, MAX_AIRPORT_SEARCHED) 
      .subscribeOn(Schedulers.io()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .subscribe(airports -> { 
       setResults(airports, excluding); 
       listener.onRegularAirportSearch(); 
       listener.onSearchPerformed(); 
      }); 


} 

それは上で実行する必要がありますように思えScheduler.io()しかし、それはメインスレッドをブロックします。

+0

サブスクリプションブロックでsetResultsを使用できますか?永久にブロックされているのですか、getSearchResultForAllが実行されている間はブロックされていますか? –

+0

@HansWurst当分ブロックされています。 DBクエリの実行が終了すると、通常に戻ります。 –

答えて

2

問題は、あなたのsearchModelsTaskであるように見えます:

public Observable<List<T>> searchModelsInView(View view, final Collection<String> searchTerms, 
     KeyMatchLevel keyMatchLevel, int queryLim) { 
    return Observable.just(
      searchModelsTask(view, new HashSet<>(searchTerms), keyMatchLevel, queryLim)); 
} 

Observable.justは、すでに値を持っていることを期待しています。したがって、observableが作成される前にsearchModelsTaskを実行しています。その結果、I/Oスケジューラに配置しようとすることはそれほど重要ではありません。すぐ内側に延期を使用してみてください:

public Observable<List<T>> searchModelsInView(View view, final Collection<String> searchTerms, 
     KeyMatchLevel keyMatchLevel, int queryLim) { 
    return Observable.defer(() -> Observable.just(
      searchModelsTask(view, new HashSet<>(searchTerms), keyMatchLevel, queryLim))); 
} 

または

public Observable<List<T>> searchModelsInView(View view, final Collection<String> searchTerms, 
      KeyMatchLevel keyMatchLevel, int queryLim) { 

return Observable.defer(new Func0<Observable<List<T>>>(){ 

     @Override 
     public Observable<List<T>> call() { 
      return Observable.just(
        searchModelsTask(view, new HashSet<>(searchTerms), keyMatchLevel, queryLim)); 
     } 
    }); 
} 

あなたはまた、同様に延期するのではなく、Observable.callable使用に見ることができます。

+0

ありがとうたくさんの男!これは正解でした! –

+0

@OmerOzer awesome :) –

関連する問題