在 RxJava 中将 Singles 链接在一起

Chaining Singles together in RxJava

我在我的 android 应用程序中使用 RxJava 以及 Retrofit 来向服务器发出网络请求。我正在使用 RxJavaCallAdapterFactory 所以我可以有我的改造请求 return 单打。在我的代码中,改装对象被命名为 'api'.

这里的代码工作正常,但在这个例子中,我需要先检索 userId,然后才能制作播放列表。我将 userId 请求平面映射到 API 请求,在制作播放列表后,我需要再次使用平面映射将 JSON 响应转换为可用对象。

public JSONUser me;

public Single<String> getUserId(){

    if(me != null){
        return Single.just(me.getUserId());
    }

    return api.getMe().flatMap(new Func1<JSONUser, Single<String>>() {
        @Override
        public Single<String> call(JSONUser meResult) {
            me = meResult;
            return Single.just(me.getUserId());
        }
    });
}

public Single<Playlist> createPlaylist(String name) {

    final NewPlaylistConfig config = new NewPlaylistConfig(name);

    return getUserId().flatMap(new Func1<String, Single<Playlist>>() {
        @Override
        public Single<Playlist> call(String userId) {
            return api.createPlaylist(userId, config).flatMap(
                    new Func1<JSONPlaylist, Single<? extends SpotifyPlaylist>>() {
                        @Override
                        public Single<? extends Playlist> call(JSONPlaylist data) {
                            return Single.just(new Playlist(data));
                    }
            });
        }
    });
}

此处的入口点是 createPlaylist()。 NewPlaylistConfig 将转换为 JSON 并且只是 POST 请求的正文参数。需要 UserId 作为路径参数。

我的主要问题是,是否有一种方法可以在没有您在此处看到的 "callback-hell" 的情况下链接这些操作。就像我说的,这段代码有效,但它真的很难看。如果有人能为此指出正确的方向,我将不胜感激。有没有办法让这项工作像 promises 一样,您可以链接 .thens?

谢谢。

而不是:

getUserId()
    .flatMap(new Func1<String, Single<Playlist>>() {
        @Override
        public Single<Playlist> call(String userId) {
            return api.createPlaylist(userId, config).flatMap(
                new Func1<JSONPlaylist, Single<? extends SpotifyPlaylist>>() {
                    @Override
                    public Single<? extends Playlist> call(JSONPlaylist data) {
                        return Single.just(new Playlist(data));
                    }
            });
        }
     });

写入:

getUserId()
    .flatMap(new Func1<String, Single<Playlist>>() {
        @Override
        public Single<Playlist> call(String userId) {
            return api.createPlaylist(userId, config);
        }
    })
    .flatMap(
        new Func1<JSONPlaylist, Single<? extends SpotifyPlaylist>>() {
            @Override
            public Single<? extends Playlist> call(JSONPlaylist data) {
                return Single.just(new Playlist(data));
            }
    });

实际上你可以像链接然后用 promises 一样链接平面图(和地图)。


注意你可以用地图替换第二个平面图,替换:

return Single.just(new Playlist(data));

与:

return new Playlist(data);

结果:

getUserId()
    .flatMap(new Func1<String, Single<Playlist>>() {
        @Override
        public Single<Playlist> call(String userId) {
            return api.createPlaylist(userId, config);
        }
    })
    .map(
        new Func1<JSONPlaylist, SpotifyPlaylist>() {
            @Override
            public SpotifyPlaylist call(JSONPlaylist data) {
                return new Playlist(data);
            }
    });

编辑:您可以进一步使用 java 8:

getUserId()
    .flatMap(userId -> api.createPlaylist(userId, config))
    .map(data -> new Playlist(data));

或科特林:

getUserId()
    .flatMap { api.createPlaylist(it, config) }
    .map { Playlist(it) }