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

Glide default only support use Activity or Fragment to create Glide.with, so we have to create SceneGlide instead

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.*

@MainThread
fun Scene.requireGlide(): RequestManager {
    ThreadUtility.checkUIThread()
    return createRequestManager(this)
}

private val lifecycleMap = ArrayMap<Scene, RequestManager>()

internal fun createRequestManager(scene: Scene): RequestManager {
    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)
        requireGlide()
                .load("https://upload.wikimedia.org/wikipedia/commons/thumb/8/80/Wikipedia-logo-v2.svg/1920px-Wikipedia-logo-v2.svg.png")
                .into(imageView)
    }
}