RXJava/Kotlin - 链接单个结果为一个
RXJava/Kotlin - Chaining Single results in one
我有一个问题,我不知道如何用更好的方法解决它。问题是我正在请求 Spotify Web API 并且在某些方法中艺术家图像是 returned 而在其他方法中只获得基本的艺术家信息。
我有这两种方法:
fun getAlbum(albumId: String): Single<SpotifyAlbumDTO>
fun getArtist(artistId: String): Single<SpotifyArtistDTO>
当我获得专辑时,艺术家信息不包含艺术家图像 url。因此,我需要调用 getAlbum() 方法并使用结果获取 artistId,然后调用 getArtist() 方法。
我有以下方法来完成所有这些事情:
fun getAlbum(albumId: String): Single<Album>
在这个方法中,我需要调用前两个来 return 一个 Album 对象(我的域对象)。唯一对我有用的解决方案如下:
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())
}
}
}
}
我认为必须存在另一种更好的方法来执行此操作,而不是在其他订阅中连接订阅调用并创建更深层次的调用。我也尝试以下操作:
_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
}
您可以使用 Pair
和 flatMap
将您的结果组合在一起:
_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
}
并行解决方案
要合并多个数据源,最好的运算符是 zip:
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())
}
它会运行所有的observable并行,并在每个observable完成后执行合并函数。
如果你有更多的 observable 可以压缩,你可以使用 Function3,Function4,...
顺序解决方案(编辑)
如果因为需要顺序执行请求而无法并行执行,那么可以使用 flatmap 函数的 resultSelector。它在平面图之前采用项目,在平面图之后采用分组集合。这样你就可以很容易地创建你的模型组,而不会混淆使用 Pair
唯一的问题是:Single
不支持这种平面图。
您可以通过将 return 类型从 Single
更改为 Observable
或仅在 运行 时使用 toObservable
运算符转换 Single
来解决此问题.
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)
}
我有一个问题,我不知道如何用更好的方法解决它。问题是我正在请求 Spotify Web API 并且在某些方法中艺术家图像是 returned 而在其他方法中只获得基本的艺术家信息。
我有这两种方法:
fun getAlbum(albumId: String): Single<SpotifyAlbumDTO>
fun getArtist(artistId: String): Single<SpotifyArtistDTO>
当我获得专辑时,艺术家信息不包含艺术家图像 url。因此,我需要调用 getAlbum() 方法并使用结果获取 artistId,然后调用 getArtist() 方法。
我有以下方法来完成所有这些事情:
fun getAlbum(albumId: String): Single<Album>
在这个方法中,我需要调用前两个来 return 一个 Album 对象(我的域对象)。唯一对我有用的解决方案如下:
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())
}
}
}
}
我认为必须存在另一种更好的方法来执行此操作,而不是在其他订阅中连接订阅调用并创建更深层次的调用。我也尝试以下操作:
_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
}
您可以使用 Pair
和 flatMap
将您的结果组合在一起:
_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
}
并行解决方案
要合并多个数据源,最好的运算符是 zip:
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())
}
它会运行所有的observable并行,并在每个observable完成后执行合并函数。
如果你有更多的 observable 可以压缩,你可以使用 Function3,Function4,...
顺序解决方案(编辑)
如果因为需要顺序执行请求而无法并行执行,那么可以使用 flatmap 函数的 resultSelector。它在平面图之前采用项目,在平面图之后采用分组集合。这样你就可以很容易地创建你的模型组,而不会混淆使用 Pair
唯一的问题是:Single
不支持这种平面图。
您可以通过将 return 类型从 Single
更改为 Observable
或仅在 运行 时使用 toObservable
运算符转换 Single
来解决此问题.
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)
}