在线程中运行时,在Retrofit和RxJava中没有调用onNext

时间:2016-07-17 17:20:08

标签: rx-java retrofit2

我正在尝试使用RxJava从Retrofit 2.1向Spotify Web API发出请求。我希望每个请求都在自己的线程中发生,结果在准备好后以任何顺序打印出来。

当前代码在主线程上执行并正常工作。但是,当我在Rx链中插入.subscribeOn(Schedulers.newThread())时,我得到一个空输出。 似乎永远不会调用onNext()。

我发现这通常是通过在Android中插入.observeOn(AndroidSchedulers.mainThread())来解决的,但是如何在常规Java 8(没有RxAndroid)中执行此操作?

public interface SpotifyService {

    @GET("tracks/{trackId}")
    Observable<SpotifyTrack> getTrack(@Path("trackId") String id);

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://api.spotify.com/v1/")
            .addConverterFactory(JacksonConverterFactory.create())
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .build();
}


public class Main {

    private static SpotifyService spotifyService = SpotifyService.retrofit.create(SpotifyService.class);

    public static void main(String[] args) {
        String[] trackIds = {
            "spotify:track:2HUI2s84pkL5815G8WI1Lg",
            "spotify:track:1bZrI1KgVKr8Qfja9cnmGh",
            "spotify:track:1WP1r7fuvRqZRnUaTi2I1Q",
            "spotify:track:5kqIPrATaCc2LqxVWzQGbk",
            "spotify:track:0mWiuXuLAJ3Brin3Or2x6v",
            "spotify:track:0BF6mdNROWgYo3O3mNGrBc"
        };

        printTrackNames(trackIds);
    }

    private static void printTrackNames(String[] trackIds) {
        Observable.from(trackIds)
            .map(Main::toTrackId)
            .flatMap(spotifyService::getTrack)
            .map(SpotifyTrack::getName)
            .subscribe(System.out::println);
    }

    private static String toTrackId(String track) {
        if (track.contains("spotify:track:")) {
            return track.split(":")[2];
        }

        return track;
    }
}

2 个答案:

答案 0 :(得分:1)

由于您没有像Android中那样继续执行的运行循环,因此您需要阻止主线程,以便它不会退出<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <!-- Identity transform --> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <xsl:template match="name"> <xsl:copy-of select="."/> <xsl:text>&#xa;</xsl:text> <xsl:text>&#9;</xsl:text> <id>9999</id> </xsl:template> </xsl:stylesheet> 并在订阅完成之前死掉。你可以使用toBlocking()

这样做

答案 1 :(得分:1)

这不是关于onNext,但是因为它在另一个线程中你无法调试它。

要证明这一点,请使用 TestSubscriber 等待观察者的完成。

这是一个证明它的单元测试。

@Test
public void testObservableAsync() throws InterruptedException {
    Subscription subscription = Observable.from(numbers)
                                          .subscribeOn(Schedulers.newThread())
                                          .subscribe(number -> System.out.println("Items emitted:" + total));
    System.out.println("I finish before the observable finish.  Items emitted:" + total);
    new TestSubscriber((Observer) subscription)
            .awaitTerminalEvent(100, TimeUnit.MILLISECONDS);
}

如果想要查看更多asyn测试,请查看https://github.com/politrons/reactive/blob/master/src/test/java/rx/observables/scheduler/ObservableAsynchronous.java