Skip to content
qiibeta edited this page Aug 17, 2022 · 11 revisions

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

import androidx.annotation.MainThread
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.OnLifecycleEvent
import androidx.lifecycle.ViewModel
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.SceneViewModelProviders
import com.bytedance.scene.utlity.ThreadUtility
import java.util.*

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

internal class GlideViewModel : ViewModel() {
    var requestManager: RequestManager? = null
}

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

    val vm = SceneViewModelProviders.of(scene).get(GlideViewModel::class.java)
    if (vm.requestManager == null) {
        val appContext = scene.requireApplicationContext()
        vm.requestManager = RequestManager(
                Glide.get(appContext),
                SceneGlideLifecycle(scene.lifecycle),
                SceneRequestManagerTreeNode(), appContext
        )
    }
    return vm.requestManager!!
}

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()
            }
            glideLifecycleListeners.clear()
            lifecycle.removeObserver(this)
        }
    }

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

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

Use requireGlide().load

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)
    }
}