Made OnIterationFinish work
diff --git a/lottie-compose/src/main/java/com/airbnb/lottie/compose/LottieAnimatable.kt b/lottie-compose/src/main/java/com/airbnb/lottie/compose/LottieAnimatable.kt
index d231f59..211caaf 100644
--- a/lottie-compose/src/main/java/com/airbnb/lottie/compose/LottieAnimatable.kt
+++ b/lottie-compose/src/main/java/com/airbnb/lottie/compose/LottieAnimatable.kt
@@ -14,6 +14,7 @@
 import kotlinx.coroutines.CancellationException
 import kotlinx.coroutines.NonCancellable
 import kotlinx.coroutines.ensureActive
+import kotlinx.coroutines.job
 import kotlinx.coroutines.withContext
 import kotlin.coroutines.EmptyCoroutineContext
 import kotlin.coroutines.coroutineContext
@@ -210,9 +211,6 @@
     ) {
         mutex.mutate {
             require(speed.isFinite()) { "Speed must be a finite number. It is $speed." }
-            require(!(iterations == LottieConstants.IterateForever && cancellationBehavior == LottieCancellationBehavior.OnIterationFinish)) {
-                "You cannot use IterateForever with LottieCancellationBehavior.OnFinish because it will never finish."
-            }
             this.iteration = iteration
             this.iterations = iterations
             this.speed = speed
@@ -231,9 +229,16 @@
                     LottieCancellationBehavior.OnIterationFinish -> NonCancellable
                     LottieCancellationBehavior.Immediately -> EmptyCoroutineContext
                 }
+                val parentJob = coroutineContext.job
                 withContext(context) {
                     while (true) {
-                        if (!doFrame()) break
+                        val actualIterations = when (cancellationBehavior) {
+                            LottieCancellationBehavior.OnIterationFinish -> {
+                                if (parentJob.isActive) iterations else iteration
+                            }
+                            else -> iterations
+                        }
+                        if (!doFrame(actualIterations)) break
                     }
                 }
                 coroutineContext.ensureActive()
@@ -243,7 +248,7 @@
         }
     }
 
-    private suspend fun doFrame(): Boolean = withFrameNanos { frameNanos ->
+    private suspend fun doFrame(iterations: Int): Boolean = withFrameNanos { frameNanos ->
         val composition = composition ?: return@withFrameNanos true
         val dNanos = if (lastFrameNanos == AnimationConstants.UnspecifiedTime) 0L else (frameNanos - lastFrameNanos)
         lastFrameNanos = frameNanos
diff --git a/lottie-compose/src/test/java/com/airbnb/lottie/compose/LottieAnimatableImplTest.kt b/lottie-compose/src/test/java/com/airbnb/lottie/compose/LottieAnimatableImplTest.kt
index 3b907a9..50367ca 100644
--- a/lottie-compose/src/test/java/com/airbnb/lottie/compose/LottieAnimatableImplTest.kt
+++ b/lottie-compose/src/test/java/com/airbnb/lottie/compose/LottieAnimatableImplTest.kt
@@ -288,15 +288,15 @@
         assertFrame(599, progress = 1f, isAtEnd = true, isPlaying = false)
     }
 
-    @Test(expected = IllegalArgumentException::class)
-    fun testCannotUseIterateForeverWithCancellationOnFinish() = runTest {
-        launch {
-            anim.animate(
-                composition,
-                cancellationBehavior = LottieCancellationBehavior.OnIterationFinish,
-                iterations = LottieConstants.IterateForever,
-            )
+    @Test
+    fun testCancelWithMultipleIterations() = runTest {
+        val job = launch {
+            anim.animate(composition, cancellationBehavior = LottieCancellationBehavior.OnIterationFinish, iterations = 3)
         }
+        assertFrame(0, progress = 0f, iterations = 3)
+        job.cancel()
+        assertFrame(300, progress = 0.5f, iterations = 3)
+        assertFrame(599, progress = 1f, isAtEnd = false, isPlaying = false, iterations = 3)
     }
 
     private suspend fun assertFrame(
diff --git a/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/examples/TransitionsExamplesPage.kt b/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/examples/TransitionsExamplesPage.kt
index da1c9e3..8414048 100644
--- a/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/examples/TransitionsExamplesPage.kt
+++ b/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/examples/TransitionsExamplesPage.kt
@@ -21,9 +21,12 @@
 import com.airbnb.lottie.compose.LottieCancellationBehavior
 import com.airbnb.lottie.compose.LottieClipSpec
 import com.airbnb.lottie.compose.LottieCompositionSpec
+import com.airbnb.lottie.compose.LottieConstants
 import com.airbnb.lottie.compose.rememberLottieComposition
 import com.airbnb.lottie.sample.compose.R
+import kotlinx.coroutines.NonCancellable
 import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.withContext
 
 enum class TransitionSection {
     Intro,
@@ -46,8 +49,17 @@
             modifier = Modifier
                 .padding(padding)
         ) {
+            Text(
+                "Single composition",
+                modifier = Modifier
+                    .padding(8.dp)
+            )
             SingleCompositionTransition(state)
-            Box(modifier = Modifier.height(16.dp))
+            Text(
+                "Multiple compositions",
+                modifier = Modifier
+                    .padding(8.dp)
+            )
             SplitCompositionTransition(state)
             TextButton(
                 onClick = { state = state.next() }
@@ -91,25 +103,22 @@
     val loopMiddleComposition = rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.bar_2))
     val outroComposition = rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.bar_3))
     val animatable = rememberLottieAnimatable()
-    val state by rememberUpdatedState(section)
 
-    LaunchedEffect(animatable) {
-        snapshotFlow { state }.collectLatest { s ->
-            val composition = when (s) {
+    LaunchedEffect(section) {
+        // Make parsing non-cancellable to ensure that every step plays at least one time.
+        val composition = withContext(NonCancellable) {
+            when (section) {
                 TransitionSection.Intro -> introComposition
                 TransitionSection.LoopMiddle -> loopMiddleComposition
                 TransitionSection.Outro -> outroComposition
             }.await()
-            do {
-                animatable.animate(
-                    composition,
-                    initialProgress = 0f,
-                    cancellationBehavior = LottieCancellationBehavior.OnIterationFinish,
-                )
-            } while (s == TransitionSection.LoopMiddle)
         }
+        animatable.animate(
+            composition,
+            iterations = if (section == TransitionSection.LoopMiddle) LottieConstants.IterateForever else 1,
+            cancellationBehavior = LottieCancellationBehavior.OnIterationFinish,
+        )
     }
 
-
     LottieAnimation(animatable.composition, animatable.progress)
 }
\ No newline at end of file