Skip to content
qiibeta edited this page Aug 13, 2021 · 11 revisions

Create SceneGlide

import androidx.annotation.MainThread
import androidx.collection.ArrayMap
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.OnLifecycleEvent
import com.bumptech.glide.Glide
import com.bumptech.glide.RequestManager
import com.bumptech.glide.manager.LifecycleListener
import com.bumptech.glide.manager.RequestManagerTreeNode
import com.bumptech.glide.util.Util
import com.bytedance.scene.Scene
import com.bytedance.scene.utlity.ThreadUtility
import java.util.*

class SceneGlide {
    companion object {
        private val lifecycleMap = ArrayMap<Scene, RequestManager>()

        @MainThread
        fun with(scene: Scene): RequestManager {
            ThreadUtility.checkUIThread()

            if (scene.lifecycle.currentState == Lifecycle.State.DESTROYED) {
                throw IllegalStateException("Scene is already destroyed.")
            }

            if (lifecycleMap[scene] == null) {
                val appContext = scene.requireApplicationContext()
                lifecycleMap[scene] = RequestManager(
                        Glide.get(appContext),
                        SceneGlideLifecycle(scene.lifecycle),
                        SceneRequestManagerTreeNode(), appContext
                )
            }
            return lifecycleMap[scene]!!
        }
    }

    private class SceneRequestManagerTreeNode : RequestManagerTreeNode {
        override fun getDescendants(): Set<RequestManager> {
            return emptySet()
        }
    }

    private class SceneGlideLifecycle(private val lifecycle: Lifecycle) : com.bumptech.glide.manager.Lifecycle {
        private val glideLifecycleListeners = Collections.newSetFromMap(WeakHashMap<LifecycleListener, Boolean>())
        private val lifecycleObserver = LifecycleAdapter()

        init {
            lifecycle.addObserver(lifecycleObserver)
        }

        inner class LifecycleAdapter : androidx.lifecycle.LifecycleObserver {
            @OnLifecycleEvent(Lifecycle.Event.ON_START)
            fun onStart(owner: LifecycleOwner) {
                val listeners = Util.getSnapshot(glideLifecycleListeners)
                for (listener in listeners) {
                    listener.onStart()
                }
            }

            @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
            fun onStop(owner: LifecycleOwner) {
                val listeners = Util.getSnapshot(glideLifecycleListeners)
                for (listener in listeners) {
                    listener.onStop()
                }
            }

            @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
            fun onDestroy(owner: LifecycleOwner) {
                val listeners = Util.getSnapshot(glideLifecycleListeners)
                for (listener in listeners) {
                    listener.onDestroy()
                }

                lifecycleMap.remove(owner)
                glideLifecycleListeners.clear()
                lifecycle.removeObserver(this)
            }
        }

        override fun addListener(listener: LifecycleListener) {
            glideLifecycleListeners.add(listener)
            when (lifecycle.currentState) {
                Lifecycle.State.STARTED -> listener.onStart()
                Lifecycle.State.DESTROYED -> listener.onDestroy()
                else -> listener.onStop()
            }
        }

        override fun removeListener(listener: LifecycleListener) {
            glideLifecycleListeners.remove(listener)
        }
    }
}

Use SceneGlide.with(scene)

class GlideScene : Scene() {
    private lateinit var imageView: ImageView

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle?): View {
        return ImageView(requireSceneContext()).also {
            imageView = it
        }
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        SceneGlide.with(this)
                .load("https://upload.wikimedia.org/wikipedia/commons/thumb/8/80/Wikipedia-logo-v2.svg/1920px-Wikipedia-logo-v2.svg.png")
                .into(imageView)
    }
}