I am working on an Android App, which needs to retrieve all the pages from network to show details on screen. This is Youtube API https://developers.google.com/youtube/v3/docs/playlistItems/list
Each response has nextPageToken, which needs to use for next page api. App is not showing list, so pagination is not needed. I am using retrofit+flow+NetworkBoundResource+mvvm+kotlin. How to use any transformation methods FlatMapMerge/FlatMapConcat/FlatMapLatest in repository to get all the response together and then emit.
restApiService
@GET(Contracts.PLAYLIST_ITEM_ENDPOINT)
fun getAllPlayListItemsForPlayListId(
@Query("part") part: String = "snippet,status",
@Query("playlistId") playlistId: String,
@Query("pageToken") pageToken: String = "",
@Query("maxResults") maxResults: Int? = 50
): Flow<ApiResponse<PlaylistItemsResponse>>
NetworkBoundResource
suspend fun asFlow(): Flow<Resource<ResultType>> {
return loadFromDb().transformLatest { dbValue ->
if (shouldFetch(dbValue)) {
emit(Resource.loading(dbValue))
createCall().collect { apiResponse ->
when (apiResponse) {
is ApiSuccessResponse -> {
withContext(Dispatchers.IO) {
saveCallResult(processResponse(apiResponse))
}
}
is ApiEmptyResponse -> {
emit(Resource.success(dbValue))
}
is ApiErrorResponse -> {
onFetchFailed()
emit(Resource.error(apiResponse.errorMessage, dbValue))
}
}
}
} else {
emit(Resource.success(dbValue))
}
}
}
Repository
override suspend fun createCall() =
apiService.getAllPlayListItemsForPlayListId(playlistId = playlistId,pageToken = nextPageToken)
How to call same apis recursively until nextPagenToken is null, like this, which is implemented in Go, referred from Youtube API guide. https://developers.google.com/youtube/v3/docs/playlistItems/list
package main
import (
"fmt"
"log"
"google.golang.org/api/youtube/v3"
)
// Retrieve playlistItems in the specified playlist
func playlistItemsList(service *youtube.Service, part string, playlistId string, pageToken
string) *youtube.PlaylistItemListResponse {
call := service.PlaylistItems.List(part)
call = call.PlaylistId(playlistId)
if pageToken != "" {
call = call.PageToken(pageToken)
}
response, err := call.Do()
handleError(err, "")
return response
}
// Retrieve resource for the authenticated user's channel
func channelsListMine(service *youtube.Service, part string) *youtube.ChannelListResponse {
call := service.Channels.List(part)
call = call.Mine(true)
response, err := call.Do()
handleError(err, "")
return response
}
func main() {
client := getClient(youtube.YoutubeReadonlyScope)
service, err := youtube.New(client)
if err != nil {
log.Fatalf("Error creating YouTube client: %v", err)
}
response := channelsListMine(service, "contentDetails")
for _, channel := range response.Items {
playlistId := channel.ContentDetails.RelatedPlaylists.Uploads
// Print the playlist ID for the list of uploaded videos.
fmt.Printf("Videos in list %s\r\n", playlistId)
nextPageToken := ""
for {
// Retrieve next set of items in the playlist.
playlistResponse := playlistItemsList(service, "snippet", playlistId, nextPageToken)
for _, playlistItem := range playlistResponse.Items {
title := playlistItem.Snippet.Title
videoId := playlistItem.Snippet.ResourceId.VideoId
fmt.Printf("%v, (%v)\r\n", title, videoId)
}
// Set the token to retrieve the next page of results
// or exit the loop if all results have been retrieved.
nextPageToken = playlistResponse.NextPageToken
if nextPageToken == "" {
break
}
fmt.Println()
}
}
}