我正在尝试为Android学习RXJAVA。部件有意义,我仍然对很多其他部分感到困惑,但是,考虑到一些时间,我希望它会更有意义。
目前我在使用“地图”时遇到了问题。功能。我收到错误但无法弄清楚如何解决。
在分享我的代码之前,我将解释我的理解...... 在一个简单的层面...... Observable - 发出数据的代码。 Observer - 处理发出数据的代码。 Map - 接收类型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);
这一切都很好......我的地图用法很相似..
我想要做的是使用同样的observable返回一个int,然后使用map代码返回一个字符串......
因此:
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中的方法映射不能应用于给定类型; 要求:功能 发现:&gt; 原因:无法推断类型变量R (参数不匹配;&gt;无法转换为Function) 其中R,T是类型变量: R扩展方法映射中声明的Object(Function) T扩展了Observable类中声明的Object
我相信这实际上告诉我这些类型对我的用法不正确,但是,我无法清楚地看到......如何解决这个问题。
b)我上面发布的地图代码并没有将observable连接到它需要观察的内容...因此,我应该在map命令之前添加订阅行吗?
因此,我试过了..
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;
}
});
}
虽然这消除了&#39; a&#39;中详述的错误。它反过来给我提供了以下错误:
错误:(180,17)错误:无法取消引用无效(这指向&#39;地图&#39;来电)
最后,我还可以看到我的回归&#39;回到地图&#39;函数根本没有被处理......我不清楚如何处理它。在这种情况下我觉得我应该使用.subscribe调用吗?
我认为&#39;我正在慢慢走上解决问题的正确道路,但我并不完全在那里,我不想在不了解问题的情况下尝试发现答案。
与往常一样,任何帮助都表示赞赏。
答案 0 :(得分:5)
这里有多个问题。有 - 一个接一个:
//Connect my Observable to the observer.
myIntObservable.observeOn(Schedulers.io());
myIntObservable.subscribeOn(AndroidSchedulers.mainThread());
myIntObservable.subscribe(myIntObserver);
上面的代码不会像您想象的那样有用。
操作员observeOn
,subscribeOn
并非旨在更改内部可观察状态。他们正在返回具有所需行为的新观察。
要完成对io()
线程的观察并在mainThread()
上订阅您的observable,您需要更改代码:
//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);
对于与您的代码相同的代码,在未更改.subscribe()
上调用Observable
将导致在您调用.subscribe()
的同一线程上进行订阅和观察(很可能来自主线程)
请记住,一旦工作完成,你需要处理observable。
说到映射问题时,map()
运算符会将一种Observable<A>
更改为另一种类型的可观察Observable<B>
。
如果您希望最终使用String
个对象转换为Integer
个对象,则需要使用 - 作为数据来源 - 原始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()
操作,对吗?)。最后提示:考虑将lambdas与RxJava一起使用。使用所有这些匿名类(new Function()
等)将使您的代码在不久的将来难以阅读。
答案 1 :(得分:1)
第一个问题是myStringObservable
会发出类String
的对象,但您正在尝试映射需要类Integer
的参数的函数。为了实现您的目标,您应该使用myIntObservable
。
第二个问题是,subscribe
调用会为您返回Disposable
个对象,之后您无法map
执行此操作。删除subscribe
电话,这应该没问题。另请注意,您的方法签名会告诉它返回String
但它不能返回String,它可以返回Observable<String>
。