首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RXJava/Kotlin - Chaining Single results in one

RXJava/Kotlin - Chaining Single results in one
EN

Stack Overflow用户
提问于 2020-01-13 05:03:50
回答 2查看 1.3K关注 0票数 2

我有一个问题,我不知道如何用更好的方法来解决它。问题是我请求Spotify Web API,在一些方法中,艺术家图像被返回,而在另一些方法中,只获得基本的艺术家信息。

我有两种方法:

代码语言:javascript
复制
fun getAlbum(albumId: String): Single<SpotifyAlbumDTO>

fun getArtist(artistId: String): Single<SpotifyArtistDTO>

当我得到一个相册时,艺术家信息不包含艺术家图像url。因此,我需要调用getAlbum()方法并使用结果来获取artistId,然后调用getArtist()方法。

我有以下方法来做所有这些事情:

代码语言:javascript
复制
fun getAlbum(albumId: String): Single<Album>

在这个方法中,我需要调用前两个方法来返回一个Album对象(我的域对象)。对我来说唯一有效的解决方案是:

代码语言:javascript
复制
fun getAlbum(albumId: String): Single<Album> {
  return Single.create { emitter ->
    _spotifyService.getAlbum(albumId).subscribe { spotifyAlbum ->
      _spotifyService.getArtist(spotifyAlbum.artist.id).subscribe { spotifyArtist ->
        val artistImage = spotifyArtist.imageUrl
        spotifyAlbum.artist.image = artistImage
        emitter.onNext(spotifyAlbum.toAlbum())
      }
    }
  }
}

我认为肯定存在另一种更好的方法来实现这一点,而不是在其他订阅中连接订阅调用并创建更深层次的调用。我还尝试了以下几种方法:

代码语言:javascript
复制
_spotifyService.getAlbum(albumId).flatMap { spotifyAlbum ->
  _spotifyService.getArtist(spotifyAlbum.artist.id)
}.flatMap { spotifyArtist ->
  // Here I don't have the album and I can't to asign the image         
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-13 07:26:04

并行求解

要组合多个数据源,最好的运算符是zip

代码语言:javascript
复制
Single.zip(getAlbum(albumId), getArtist(artistId),
    BiFunction<SpotifyAlbumDTO, SpotifyArtistDTO, SpotifyAlbumDTO> { album, artist -> 
        val artistImage = artist.imageUrl
        album.artist.image = artistImage
        album //return value of the merged observable 
    }
).subscribe { album: SpotifyAlbumDTO?, error: Throwable? ->
    emitter.onNext(album.toAlbum())
}

它将并行运行所有可观测对象,并在每个可观测对象完成后执行合并函数。

如果你有更多可观察的压缩,你可以使用Function3,Function4,...

顺序解决方案(编辑)

如果由于您需要按顺序执行请求而无法并行执行,那么您可以使用flatmap函数的resultSelector。它在flatmap之前获取项,在平面映射之后获取分组集合。这样,您就可以轻松地创建模型组,而不会混淆Pair的用法

唯一的问题是:Single不支持这种平面映射。您可以解决此问题,或者将返回类型从Single更改为Observable,或者在运行时使用toObservable运算符转换Single

代码语言:javascript
复制
getAlbum(albumId)
    .toObservable()
    .flatMap({album: SpotifyAlbumDTO -> getArtist(album.artist.id).toObservable()},
             { album:SpotifyAlbumDTO, artist:SpotifyArtistDTO ->
                 album.artist.image = artist.imageUrl
                 album
             })
    }?.subscribe { album: SpotifyAlbumDTO ->
        print(album)
    }
票数 2
EN

Stack Overflow用户

发布于 2020-01-13 05:27:01

您可以使用带有flatMapPair将您的结果打包在一起:

代码语言:javascript
复制
_spotifyService.getAlbum(albumId).flatMap { spotifyAlbum ->
  _spotifyService.getArtist(spotifyAlbum.artist.id)
       .flatMap { artist ->
           Single.just(spotifyAlbum, artist)
       }
}.subscribe { pair: Pair<Album, Artist> ->
  // grab results
  val album = pair.first
  val artist = pair.second      
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59708108

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档