使用rxJava2在改造中​​链接请求,并在recyclerview中填充结果

时间:2018-09-01 13:55:07

标签: android kotlin retrofit2 rx-java2

我正在尝试使用thesportsdb中的API来显示特定联赛的最后一场比赛。在我的recyclerview中,我想显示每个团队的团队徽章,但是当我请求lastmatch API时,它不包含团队徽章,仅显示每个团队的ID,如果我想显示徽章,它要求我请求团队个人资料,其中包含团队徽章的网址。

由于我是rxJava的新手,所以我仍然熟悉它。有些帖子建议使用Flatmap,但是像我这样的初学者很难实现。

这是retrofitService:

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

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

2 个答案:

答案 0 :(得分:1)

对于第二个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取决于第一个的结果,则只需使用it运算符内的map变量并将其传递到所需的任何位置。因此,如果使用前面的示例,则您的代码可以转换为:

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

答案 1 :(得分:0)

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

您可以通过组合 flatmap zip 运算符来实现。看起来类似于以下内容,其中MatchData既包含FootballMatch数据,也包含homeTeam和awayTeam数据。

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

然后,您的平面图操作将需要为主队和客队调用getTeams方法,然后可以通过zip操作器将其与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)
            })
}