web-dev-qa-db-ja.com

RxJavaでシングルをチェーンする

AndroidアプリでRetroxと一緒にRxJavaを使用して、サーバーにネットワークリクエストを送信しています。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));
                    }
            });
        }
    });
}

ここでのエントリポイントはcreatePlaylist()です。 NewPlaylistConfigはJSONに変換され、POSTリクエストのbodyパラメータです。パスパラメータとしてUserIdが必要です。

ここでの私の主な質問は、ここに表示される「コールバック地獄」なしでこれらの操作をチェーンする方法があるかどうかです。私が言ったように、このコードは機能しますが、それは本当に醜いです。これに関して誰かが私を正しい方向に向けてくれれば幸いです。あなたが.thensをチェーンすることができるpromiseのようにこれを機能させる方法はありますか?

ありがとうございました。

16
Jtvd78

の代わりに:

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));
            }
    });

実際には、プロミスでチェーンするようにフラットマップ(およびマップ)をチェーンできます。


2番目のフラットマップをmapに置き換えることができます。

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));

またはKotlin:

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