2017-05-17 54 views
0

我正在嘗試爲Android學習RXJAVA。部分是有意義的,我仍然對很多其他位置感到困惑,但是,給我一些時間,我希望它會更有意義。在RxJava 2/RxAndroid中使用'map'的問題2

目前我遇到了「地圖」功能問題。我收到一個錯誤,但無法完全弄清楚如何解決它。

在我分享我的代碼之前,我會解釋我的理解.. 在簡單的層次上.. Observable - 發射數據的代碼。 觀察者 - 處理髮射數據的代碼。 地圖 - 代碼,發生在A型的數據,並返回其加工或類型B.

因此,考慮到這一點:

在gradle這個我有:

compile 'io.reactivex.rxjava2:rxjava:2.0.1' 
compile 'io.reactivex.rxjava2:rxandroid:2.0.1' 

如果我有:

//declaration at top of file 
    private Observable<Integer> myIntObservable; 
    private Observer<Integer> myIntObserver; 
    private Observer<String> myStringObserver; 
    private Observable<String> myStringObservable; 

    //usage in a function 
    myIntObserver = new Observer<Integer>() { 
     @Override 
     public void onSubscribe(Disposable d) { 

     } 

     @Override 
     public void onNext(Integer value) { 
      Toast.makeText(getApplicationContext(), "" + value, Toast.LENGTH_SHORT).show(); 
     } 

     @Override 
     public void onError(Throwable e) { 

     } 

     @Override 
     public void onComplete() { 
      Toast.makeText(getApplicationContext(), "Int Observer Async Complete", Toast.LENGTH_SHORT).show(); 
     } 
    }; 


    //Connect my Observable to the observer. 
    myIntObservable.observeOn(Schedulers.io()); 
    myIntObservable.subscribeOn(AndroidSchedulers.mainThread()); 
    myIntObservable.subscribe(myIntObserver); 

這一切工作正常...我的地圖使用類似..

我想要做的是使用返回一個int此相同的觀察到的,然後使用地圖代碼,改爲返回一個字符串...

因此:

myStringObservable 
      .observeOn(Schedulers.io()) 
      .subscribeOn(AndroidSchedulers.mainThread()) 
      .map(new Function<Integer, String>() { 
       @Override 
       public String apply(Integer query){ 
        return "String Observable result == " + query; 
       } 
      }); 

現在,我有兩個問題:

a)我收到的構建錯誤是: 錯誤:(179,17)錯誤:類Observable中的方法映射無法應用於給定的類型; 需要:發現功能 :> 原因:不能推斷類型變量(S)R (自變量不匹配;>不能被轉換爲功能) 其中R,T是類型的變量: ř延伸方法映射對象聲明(功能) 牛逼擴展類可觀察

聲明的對象我認爲這基本上是告訴我,類型是不是我的使用正確的,但,我不能清楚地看到...如何解決這個問題。

b)我上面發佈的地圖代碼並沒有將observable連接到它需要觀察的東西......因此,我應該在map命令之前添加subscribe行嗎?

因此,我想這..

public void setupAsyncSubscription(){ 

    myIntObservable 
      .observeOn(Schedulers.io()) 
      .subscribeOn(AndroidSchedulers.mainThread()) 
      .subscribe(myIntObserver) 
      .map(new Function<Integer, String>() { 
       @Override 
       public String apply(Integer query){ 
        return "String Observable result == " + query; 
       } 
      }); 

} 

雖然這消除在 'A',而不是它爲我提供以下錯誤詳述的錯誤:

錯誤:(180,17)錯誤: void無法解除引用(這指向'map'調用)

最後,我還可以看到,我從'map'函數返回的內容沒有得到處理......我是不清楚如何處理。我覺得我應該在這種情況下使用.subscribe調用?

我'認爲'我正在慢慢地走正確的道路來解決問題,但我並不是那樣,我不想在沒有理解問題的情況下嘗試發生答案。是。

一如既往,任何幫助表示讚賞。

回答

4

這裏有多個問題。有 - 一個接一個:

//Connect my Observable to the observer. 
myIntObservable.observeOn(Schedulers.io()); 
myIntObservable.subscribeOn(AndroidSchedulers.mainThread()); 
myIntObservable.subscribe(myIntObserver); 

上面的代碼不會像你想象的那樣工作。

運營商observeOn, subscribeOn不旨在改變內部可觀察狀態。他們正在以期望的行爲返回新的可觀察者。

要完成觀察對io()線程和訂閱您觀察到的mainThread()您需要更改代碼:

//Connect my Observable to the observer. 
myIntObservable = myIntObservable.observeOn(Schedulers.io()); 
myIntObservable = myIntObservable.subscribeOn(AndroidSchedulers.mainThread()); 
myIntObservable.subscribe(myIntObserver); 

或者使用(首選)鏈接:

//Connect my Observable to the observer. 
myIntObservable 
    .observeOn(Schedulers.io()); 
    .subscribeOn(AndroidSchedulers.mainThread()); 
    .subscribe(myIntObserver); 

的代碼一樣的你,撥打.subsribe()未更改Observable將導致訂閱和觀察您從中調用.subscribe()(很可能來自主線程)的同一線程。

請記住,您需要在工作完成後處置observable。

當涉及到映射問題 - map()運營商更改一種類型Observable<A>到另一種類型的可觀察<Observable<B>

如果您想從Integer對象轉換String對象,最終你需要使用 - 作爲數據源 - 你原來myIntObservable

myStringObservable = myIntObservable 
    (...)  
    .map(new Function<Integer, String>() { 
     @Override 
     public String apply(Integer query){ 
      return "String Observable result == " + query; 
     } 
    }); 

在上面的例子中myIntObservable會發出Integer對象(如.apply(Integer query)方法所示,然後.map()運營商將創建另一Observable類型Observable<String>您可以分配給myStringObservable(或做任何你想從這裏)。

然後,使用myStringObservable您可以訂閱其事件:

myStringObservable.subscribe(myStringObserver) 

再次,請記住處置Observable時,工作就完成了。

也請注意,你應該:

  • .observeOn()儘快對當前的一件工作,
  • .subscribeOn()儘可能晚的(你不想繼續io()computation()操作您的主線程,對不對?)。

提示:結束時考慮使用帶RxJava的lambdas。使用所有這些匿名類(new Function()等)將使您的代碼在最近的將來難以閱讀。

+0

嗨。感謝您抽出時間回覆並提供詳細的回覆。 我已根據您的答案修改了我的代碼,現在它的行爲符合我的要求。謝謝你。 我有一個最後的查詢......你提到我應該在處理完Observable後才能處理它..我明白爲什麼,但我對如何進行混淆。我看不到任何方法,例如.dispose,我可以在'onComplete'之後調用...我期望能夠執行諸如myStringObservable.dispose()之類的操作,並且我無法將myStringObservable指派給Disposable ... – greysqrl

+0

使用'DisposableObserver'。或者更好 - 而不是使用觀察者,使用'Consumer's(所有.subscribe()方法爲消費者返回'Disposable's)。然後你可以使用'CompositeDisposable'來輕鬆處理多個觀測值。 – tommus

1

第一個問題是myStringObservable會發出String類的對象,但您試圖映射需要類Integer參數的函數。爲了實現你想要的,你應該使用myIntObservable

第二個問題是,subscribe調用返回一個Disposable對象爲你,你不能再做map。刪除那subscribe電話,這應該沒問題。還請注意,您的方法簽名告訴它返回String,但它不能返回字符串,它可以返回Observable<String>

+0

嗨。感謝您花時間回覆並解釋您提供的內容。 – greysqrl