使用 rxJava2 链接改造中的请求,并在回收器视图中填充结果



我正在尝试使用来自thesportsdb的API来显示特定联赛的最后一场比赛。 在我的回收器视图中,我想显示每个团队的团队徽章,但是当我请求最后匹配 API 时,它不包括团队徽章,只包括每个团队的 ID,如果我想显示徽章,它需要我请求包含团队徽章 url 的团队资料。

由于我是rxJava的新手,所以我仍然熟悉它。 一些帖子建议使用平面地图,但对于像我这样的初学者来说,实现它有点困难。

这是改造服务:

interface FootballRest {
@GET("eventspastleague.php")
fun getLastmatch(@Query("id") id:String) : Flowable<FootballMatch>
@GET("lookupteam.php")
fun getTeam(@Query("id") id:String) : Flowable<Teams>
}

我使用了存储库模式

class MatchRepositoryImpl(private val footballRest: FootballRest) : MatchRepository {
override fun getFootballMatch(id: String): Flowable<FootballMatch> = footballRest.getLastmatch(id)
override fun getTeams(id: String): Flowable<Teams> = 
footballRest.getTeam(id)
}

这是进行调用并将数据发送到视图的演示者:

class MainPresenter(val mView : MainContract.View, val matchRepositoryImpl: MatchRepositoryImpl) : MainContract.Presenter{
val compositeDisposable = CompositeDisposable()
val requestMatch = matchRepositoryImpl.getFootballMatch("4328")
val requestTeam = matchRepositoryImpl.getTeams()
override fun getFootballMatchData() {
compositeDisposable.add(matchRepositoryImpl.getFootballMatch("4328")
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe{
mView.displayFootballMatch(it.events)
})
}

到目前为止,我只显示最后一场比赛的结果,但我也想在列表中显示徽章团队。

您可以将map运算符与lastElement().blockingGet()结合使用进行第二次Observable,然后返回Pair结果。一个简单的例子如下:

@Test
public fun test1() {
Observable.just(1)
.map {
// here 'it' variable is calculated already so it can be passed to the second observable
val result = Observable.just(2).lastElement().blockingGet()
Pair<Int, Int>(it, result)
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { t -> System.out.println("First : " + t?.first + ", second : " + t?.second) }
Thread.sleep(1000)
}

输出

1 2

如果您的第二个Observable取决于第一个的结果,那么只需在map运算符中使用it变量并将其传递到需要的任何位置。因此,如果使用前面的示例,您的代码可以转换为以下内容:

override fun getFootballMatchData() {
compositeDisposable.add(matchRepositoryImpl.getFootballMatch("4328").toObservable( 
.map {
// here 'it' variable is calculated already so it can be passed to the second observable
val next = matchRepositoryImpl.getTeams(it).toObservable().lastElement().blockingGet()
Pair<Int, Int>(it, next)
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe{ t ->
mView.displayFootballMatch(t.first)
mView.displayBadgeTeam(t.second)
})
}

与其使用blockingGet 运算符,不如使用平面图并将所有这些数据作为单个流返回。

您可以通过组合平面图zip运算符来实现此目的。这看起来像下面这样,其中MatchData保存FootballMatch数据以及主队和客队数据。

data class MatchData(val footballMatch: FootballMatch, val homeTeam: Teams, val awayTeam: Teams)

然后,您的平面地图操作需要为主队和客队调用 getTeams 方法,然后可以通过 zip oprator 与 footballMatch 数据相结合。

override fun getFootballMatchData() {
compositeDisposable.add(matchRepositoryImpl.getFootballMatch("4328")
.subscribeOn(Schedulers.io())
.flatMap { footballMatch ->
Flowable.zip(
matchRepositoryImpl.getTeams(footballMatch.idHomeTeam),
matchRepositoryImpl.getTeams(footballMatch.idAwayTeam),
BiFunction { homeTeam: Teams, awayTeam: Teams ->
MatchData(
footballMatch = footballMatch,
homeTeam = homeTeam,
awayTeam = awayTeam)
}
)
}
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
mView.displayFootballMatch(it)
})
}

最新更新