在RxJava中链接单打

Jtv*_*d78 14 android promise chain rx-java

我在我的Android应用程序中使用RxJava和Retrofit向服务器发出网络请求.我正在使用RxJavaCallAdapterFactory,所以我可以让我的改装请求返回单打.在我的代码中,改造对象被命名为'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));
                    }
            });
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

这里的入口点是createPlaylist().NewPlaylistConfig将转换为JSON,并且只是POST请求的body参数.需要UserId作为路径参数.

我在这里的主要问题是,如果有一种方法可以将这些操作链接起来而没有你在这里看到的"回调 - 地狱".就像我说的,这段代码有效,但它真的很难看.如果有人能指出我正确的方向,我将不胜感激.有没有办法使这项工作像承诺,你可以链接.thens?

谢谢.

Geo*_*izy 18

代替:

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));
                    }
            });
        }
     });
Run Code Online (Sandbox Code Playgroud)

写:

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));
            }
    });
Run Code Online (Sandbox Code Playgroud)

实际上你可以链接flatmap(和map),就像你链接promises一样.


请注意,您可以使用地图替换第二个flatmap,替换:

return Single.just(new Playlist(data));
Run Code Online (Sandbox Code Playgroud)

有:

return new Playlist(data);
Run Code Online (Sandbox Code Playgroud)

结果:

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);
            }
    });
Run Code Online (Sandbox Code Playgroud)

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

getUserId()
    .flatMap(userId -> api.createPlaylist(userId, config))
    .map(data -> new Playlist(data));
Run Code Online (Sandbox Code Playgroud)

或者Kotlin:

getUserId()
    .flatMap { api.createPlaylist(it, config) }
    .map { Playlist(it) }
Run Code Online (Sandbox Code Playgroud)