1

I am trying to consume an API from thesportsdb to display lastmatch from specific league. in my recyclerview I want to show the team badge for every teams but when I request the lastmatch API it didn't include the team badge, only the id for each team and if I want to show the badge it require me to request the team profile which includes the url for the team badge.

Since I am new to rxJava so I am still familiarize myself with it. some posts suggest using flatmap but it kind a difficult for beginner like me to implement it.

this is the 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>
}

I used repository pattern

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

and this is the presenter who make the call and send the data to the view:

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

so far I only show the last match result, but I want also to show the badge team on the list.

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
mangkool
  • 316
  • 2
  • 18

2 Answers2

1

You could use a map operator combined with lastElement().blockingGet() for the second Observable for this and then return a Pair of results. A simple example could be as follows:

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

Output

1 2

If your second Observable depends on the result of the first one then just use the it variable inside the map operator and pass it to whatever place it's needed. So, if using the previous example your code could be converted to this:

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)
            })
}
Anatolii
  • 14,139
  • 4
  • 35
  • 65
  • Thank you for your answer, but in order to call the getTeam function I need to pass an id parameter which should be emited from the getFootballMatch function – mangkool Sep 01 '18 at 15:02
  • thanks, I haven't tried your answer, I will update the answer soon I've tried it – mangkool Sep 02 '18 at 10:44
0

Rather than use a blockingGet operator its probably easier for you to use a flatmap and return all of this data as a single stream.

You could achieve this by combining the flatmap and zip operator. This would look something like the following, where MatchData holds both the FootballMatch data along with the homeTeam and awayTeam data.

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

Your flatmap operation would then need to invoke the getTeams method for both home and away team which can then be combined with the footballMatch data through the zip oprator.

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)
            })
}
Chris
  • 2,332
  • 1
  • 14
  • 17