使用' map'的问题在RxJava 2 / RxAndroid 2中

时间:2017-05-17 08:41:54

标签: java android rx-java reactive-programming rx-android

我正在尝试为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;我正在慢慢走上解决问题的正确道路,但我并不完全在那里,我不想在不了解问题的情况下尝试发现答案。

与往常一样,任何帮助都表示赞赏。

2 个答案:

答案 0 :(得分:5)

这里有多个问题。有 - 一个接一个:

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

上面的代码不会像您想象的那样有用。

操作员observeOnsubscribeOn并非旨在更改内部可观察状态。他们正在返回具有所需行为的新观察。

要完成对io()线程的观察并在mainThread()上订阅您的o​​bservable,您需要更改代码:

//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>