2017-05-17 23 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