pop
pop

Reputation: 37

Kotlin for loop does not wait for function to finish

I have the following for loop.

for (song in songArray){
    playSong(song)
}

and playSong as below:

fun playSong(song){
mediaPlayer.create(context, R.raw.song)
mediaPlayer.start

mediaPlayer?.setOnCompletionListener {
        mediaPlayer!!.release()
        mediaPlayer = null
        }
}

The for loop does not wait for the entire playSong function to complete, and just immediately starts the next song. I want the the listener to be heard and the song to complete before iterating to the next song. If you could give me some guidance on this, I would appreciate it.

Upvotes: 0

Views: 1173

Answers (2)

Tenfour04
Tenfour04

Reputation: 93551

Here's how it could be done with coroutines. First, you need to create a suspend function version of playing media and waiting for it to finish. Since a completion listener is not a one-shot callback, I think it is more appropriate to use callbackFlow instead of suspendCoroutine.

suspend fun MediaPlayer.startAndAwait() { 
    callbackFlow { 
        setOnCompletionListener {
            trySendBlocking(Unit)
        }
        awaitClose { setOnCompletionListener(null) }
    }.first()
    start()
}

Then you can use this function in a coroutine, so you can loop sequentially:

suspend fun playSong(song: Int){
    MediaPlayer.create(context, song).apply {
        mediaPlayer = this // so you can cancel playback from elsewhere
        startAndAwait()
        release()
        mediaPlayer = null
    }
}

//In a coroutine:

for (song in songArray){
    playSong(song)
}

Upvotes: 3

Vojin Purić
Vojin Purić

Reputation: 2376

Instead of using for loop play songs from array when the previous one finishes

fun playSongArray(songArray: IntArray) {
    var i = 0
    mediaPlayer.create(context, R.raw.songArray[0])
    mediaPlayer.start
    mediaPlayer?.setOnCompletionListener {
        if (i < songArray.size) {
            mediaPlayer.create(context, R.raw.songArray[1])
            mediaPlayer.start
            i++
        } else {
            mediaPlayer!!.release()
            mediaPlayer = null
        }
    }
}

Upvotes: 2

Related Questions