@@ -35,6 +35,7 @@ import kotlinx.coroutines.Dispatchers
3535import kotlinx.coroutines.Job
3636import kotlinx.coroutines.SupervisorJob
3737import kotlinx.coroutines.cancel
38+ import kotlinx.coroutines.isActive
3839import kotlinx.coroutines.launch
3940import kotlinx.coroutines.withContext
4041import com.dotlottie.dlplayer.Config as DLConfig
@@ -70,7 +71,7 @@ class DotLottieAnimation @JvmOverloads constructor(
7071 private var height: Int = 0
7172 private var mConfig: Config ? = null
7273 private var mLottieDrawable: DotLottieDrawable ? = null
73- private val coroutineScope = CoroutineScope (SupervisorJob ())
74+ private var coroutineScope = CoroutineScope (SupervisorJob ())
7475 private var setupConfigJob: Job ? = null
7576 private var setupDrawableJob: Job ? = null
7677 private var layoutListener: ViewTreeObserver .OnGlobalLayoutListener ? = null
@@ -337,8 +338,8 @@ class DotLottieAnimation @JvmOverloads constructor(
337338 layoutListener = object : ViewTreeObserver .OnGlobalLayoutListener {
338339 override fun onGlobalLayout () {
339340 if (width > 0 && height > 0 ) {
340- // Start animation setup only when dimensions are available
341- setupDotLottieDrawable ()
341+ // Start animation setup only when dimensions are available.
342+ setupDrawableIfNeeded ()
342343 // Remove the listener to avoid redundant calls
343344 removeLayoutListener()
344345 }
@@ -365,8 +366,24 @@ class DotLottieAnimation @JvmOverloads constructor(
365366 }
366367
367368
369+ private fun ensureScopeActive () {
370+ if (! coroutineScope.isActive) {
371+ coroutineScope = CoroutineScope (SupervisorJob ())
372+ }
373+ }
374+
375+ private fun setupDrawableIfNeeded () {
376+ if (mLottieDrawable != null ) return
377+ if (setupConfigJob?.isActive == true || setupDrawableJob?.isActive == true ) return
378+ when {
379+ mConfig != null -> setupConfig()
380+ ::attributes.isInitialized && attributes.src.isNotBlank() -> setupDotLottieDrawable()
381+ }
382+ }
383+
368384 private fun setupConfig () {
369385 val config = mConfig ? : return
386+ ensureScopeActive()
370387 setupConfigJob?.cancel()
371388 setupConfigJob = coroutineScope.launch {
372389 runCatching {
@@ -416,6 +433,7 @@ class DotLottieAnimation @JvmOverloads constructor(
416433 }
417434
418435 private fun setupDotLottieDrawable () {
436+ ensureScopeActive()
419437 setupDrawableJob?.cancel()
420438 setupDrawableJob = coroutineScope.launch {
421439 runCatching {
@@ -426,6 +444,8 @@ class DotLottieAnimation @JvmOverloads constructor(
426444 DotLottieUtils .getContent(context, DotLottieSource .Asset (attributes.src))
427445 }
428446
447+ if (! isActive || ! this @DotLottieAnimation.isAttachedToWindow) return @launch
448+
429449 mLottieDrawable = DotLottieDrawable (
430450 animationData = content,
431451 width = width,
@@ -482,6 +502,17 @@ class DotLottieAnimation @JvmOverloads constructor(
482502 }
483503 }
484504
505+ override fun onAttachedToWindow () {
506+ super .onAttachedToWindow()
507+ if (mLottieDrawable == null ) {
508+ if (width > 0 && height > 0 ) {
509+ setupDrawableIfNeeded()
510+ } else if (layoutListener == null ) {
511+ waitForLayout()
512+ }
513+ }
514+ }
515+
485516 override fun onDetachedFromWindow () {
486517 super .onDetachedFromWindow()
487518 removeLayoutListener()
0 commit comments