Kotlin实现Glide/Coil图/视频加载框架(二)

Kotlin实现Glide/Coil图/视频加载框架(二)

https://blog.csdn.net/zhangphil/article/details/150206845 基础上抽象封装,实现一种总体的图视频加载框架。增加磁盘缓存读写策略。

Kotlin 复制代码
enum class DiskCachePolicy {
    READ_ONLY,//只读缓存,不写缓存
    WRITE_ONLY,//跳过缓存读,只缓存写
    READ_WRITE,//既缓存读,又缓存写
    NONE //不读缓存,也不写缓存. 不使用任何缓存策略。
}
Kotlin 复制代码
import kotlin.random.Random

open class Fetcher<D : Item, R : Result?> {
    companion object {
        const val TAG = "Fetcher"
    }

    private var mItem: D? = null
    private var mDiskCachePolicy = DiskCachePolicy.NONE

    constructor(item: D) {
        mItem = item
    }

    fun fetch(): R? {
        println("$TAG 缓存策略=${getDiskCachePolicy()}")

        var result: R? = null
        when (getDiskCachePolicy()) {
            DiskCachePolicy.NONE -> {
                result = readRaw()
            }

            DiskCachePolicy.READ_ONLY -> {
                val cacheExist = checkDiskCacheExist()
                println("$TAG $mItem 本地缓存状态=$cacheExist")

                if (cacheExist) {
                    result = readCache()
                }

                if (result == null) {
                    result = readRaw()
                }
            }

            DiskCachePolicy.WRITE_ONLY -> {
                result = readRaw()

                if (result != null) {
                    val cacheExist = checkDiskCacheExist()
                    println("$TAG $mItem 本地缓存状态=$cacheExist")
                    if (!cacheExist) {
                        writeCache(mItem, result)
                    }
                }
            }

            DiskCachePolicy.READ_WRITE -> {
                val cacheExist = checkDiskCacheExist()
                println("$TAG $mItem 本地缓存状态=$cacheExist")

                if (cacheExist) {
                    result = readCache()
                }

                if (result == null) {
                    result = readRaw()
                }

                if (result != null) {
                    if (!cacheExist) {
                        writeCache(mItem, result)
                    }
                }
            }

            else -> {
                TODO()
            }
        }

        return result
    }

    open fun readRaw(): R? {
        val result = longTimeRawFileIoRead(mItem!!)
        return result as R?
    }

    private fun readCache(): R? {
        if (Random.nextBoolean()) {
            //特意制造读缓存失败的场景,测试架构的适应性和鲁棒性。
            println("$TAG $mItem 读本地缓存发生异常")
            return null
        } else {
            val result = longTimeCacheFileIoRead(mItem!!)
            return result as R?
        }
    }

    //假设这里是耗时的IO读文件任务,把缓存在文件里面的数据读出来.
    private fun longTimeCacheFileIoRead(item: D): R? {
        val result = Result()
        result.req = item
        result.data = System.currentTimeMillis()

        Thread.sleep(100)

        println("$TAG $item 读取缓存数据 $result")

        return result as R?
    }

    //模拟耗时的IO读文件任务,把本地原始文件里面的数据读出来.
    private fun longTimeRawFileIoRead(item: D): R? {
        val result = Result()
        result.req = item
        result.data = System.currentTimeMillis()

        Thread.sleep(1000)

        println("$TAG $item 读原始数据 $result")

        return result as R?
    }

    private fun writeCache(item: D?, result: R?) {
        longTimeCacheFileWrite(item, result)
    }

    //假设这里是长时间的耗时写缓存文件操作。
    private fun longTimeCacheFileWrite(item: D?, result: R?) {
        Thread.sleep(100)
        println("$TAG $item $result longTimeCacheFileWrite() 写入本地缓存")
    }

    fun setDiskCachePolicy(diskCachePolicy: DiskCachePolicy) {
        mDiskCachePolicy = diskCachePolicy
    }

    open fun getDiskCachePolicy(): DiskCachePolicy {
        return mDiskCachePolicy
    }

    //模拟检查本地缓存是否存在.
    //这一过程需要检查本地缓存文件中是否存在文件缓存,耗时操作。
    private fun checkDiskCacheExist(): Boolean {
        Thread.sleep(10)
        val exist = Random.nextBoolean()
        return exist
    }
}
Kotlin 复制代码
class GifFetcher : Fetcher<Item, Result?> {
    constructor(item: GifItem) : super(item) {
    }
}
Kotlin 复制代码
class GifItem : Item {
    constructor() {
        type = GIF
    }
}
Kotlin 复制代码
open class Item : Any {
    companion object {
        const val VIDEO = 1
        const val GIF = 2
    }

    var type = -1
    var timestamp = System.nanoTime()

    constructor() {

    }

    override fun toString(): String {
        return "Item(type=$type, timestamp=$timestamp)"
    }
}
Kotlin 复制代码
class Loader {

    companion object {
        private var mLoader: Loader? = null

        fun build(): Loader {
            val loader = Loader()
            mLoader = loader

            return mLoader!!
        }
    }

    private var mListener: Listener? = null
    private var mFetcher: Fetcher<Item, Result?>? = null

    constructor() {

    }

    fun setFetch(fetcher: Fetcher<Item, Result?>): Loader {
        mFetcher = fetcher

        return mLoader!!
    }

    fun setCachePolicy(cachePolicy: DiskCachePolicy): Loader {
        mFetcher?.setDiskCachePolicy(cachePolicy)

        return mLoader!!
    }

    fun setListener(listener: Listener): Loader {
        mListener = listener

        return mLoader!!
    }

    fun load() {
        val result = mFetcher?.fetch()
        mListener?.onSuccess(result)
    }

    interface Listener {
        fun onSuccess(result: Result?) {}
        fun onFail(e: Exception) {}
    }
}
Kotlin 复制代码
class Result {
    var req: Item? = null
    var tag: Any? = null
    var data: Any? = null

    override fun toString(): String {
        return "Result(req=$req, tag=$tag, data=$data)"
    }
}
Kotlin 复制代码
class VideoFetcher : Fetcher<Item, Result?> {
    companion object {
        const val TAG = "VideoFetcher"
    }

    private var mItem: VideoItem? = null

    constructor(item: VideoItem) : super(item) {
        mItem = item
    }

    override fun readRaw(): Result? {
        val result = Result()
        result.req = mItem
        println("$TAG $mItem 读原始数据")
        return result
    }

    override fun getDiskCachePolicy(): DiskCachePolicy {
        return DiskCachePolicy.READ_WRITE
    }
}
Kotlin 复制代码
class VideoItem : Item {
    constructor(){
        type = VIDEO
    }
}

测试的main函数:

Kotlin 复制代码
import kotlin.random.Random

fun main() {
    //测试
    (0..3).forEach { _ ->
        Loader.build()
            .setFetch(GifFetcher(GifItem()))
            .setCachePolicy(getDiskCachePolicy())
            .setListener(object : Loader.Listener {
                override fun onSuccess(result: Result?) {
                    println("main $result ${result?.req}")
                }
            }).load()

        println("---")
    }

    Loader.build()
        .setFetch(VideoFetcher(VideoItem()))
        .setListener(object : Loader.Listener {
            override fun onSuccess(result: Result?) {
                println("main $result ${result?.req}")
            }
        }).load()
}


//随机生成测试的缓存策略
private fun getDiskCachePolicy(): DiskCachePolicy {
    val rand = Random.nextInt(DiskCachePolicy.entries.size)
    var diskCachePolicy = DiskCachePolicy.NONE

    when (rand) {
        DiskCachePolicy.READ_ONLY.ordinal -> {
            diskCachePolicy = DiskCachePolicy.READ_ONLY
        }

        DiskCachePolicy.WRITE_ONLY.ordinal -> {
            diskCachePolicy = DiskCachePolicy.WRITE_ONLY
        }

        DiskCachePolicy.READ_WRITE.ordinal -> {
            diskCachePolicy = DiskCachePolicy.READ_WRITE
        }

        DiskCachePolicy.NONE.ordinal -> {
            diskCachePolicy = DiskCachePolicy.NONE
        }

        else -> {

        }
    }

    return diskCachePolicy
}

运行输出:

Fetcher 缓存策略=READ_WRITE

Fetcher Item(type=2, timestamp=884027990900) 本地缓存状态=true

Fetcher Item(type=2, timestamp=884027990900) 读取缓存数据 Result(req=Item(type=2, timestamp=884027990900), tag=null, data=1768442150276)

main Result(req=Item(type=2, timestamp=884027990900), tag=null, data=1768442150276) Item(type=2, timestamp=884027990900)


Fetcher 缓存策略=READ_ONLY

Fetcher Item(type=2, timestamp=884169920800) 本地缓存状态=false

Fetcher Item(type=2, timestamp=884169920800) 读原始数据 Result(req=Item(type=2, timestamp=884169920800), tag=null, data=1768442150400)

main Result(req=Item(type=2, timestamp=884169920800), tag=null, data=1768442150400) Item(type=2, timestamp=884169920800)


Fetcher 缓存策略=WRITE_ONLY

Fetcher Item(type=2, timestamp=885198545700) 读原始数据 Result(req=Item(type=2, timestamp=885198545700), tag=null, data=1768442151413)

Fetcher Item(type=2, timestamp=885198545700) 本地缓存状态=false

Fetcher Item(type=2, timestamp=885198545700) Result(req=Item(type=2, timestamp=885198545700), tag=null, data=1768442151413) longTimeCacheFileWrite() 写入本地缓存

main Result(req=Item(type=2, timestamp=885198545700), tag=null, data=1768442151413) Item(type=2, timestamp=885198545700)


Fetcher 缓存策略=READ_WRITE

Fetcher Item(type=2, timestamp=886325747400) 本地缓存状态=true

Fetcher Item(type=2, timestamp=886325747400) 读取缓存数据 Result(req=Item(type=2, timestamp=886325747400), tag=null, data=1768442152556)

main Result(req=Item(type=2, timestamp=886325747400), tag=null, data=1768442152556) Item(type=2, timestamp=886325747400)


Fetcher 缓存策略=READ_WRITE

Fetcher Item(type=1, timestamp=886448708000) 本地缓存状态=true

Fetcher Item(type=1, timestamp=886448708000) 读本地缓存发生异常

VideoFetcher Item(type=1, timestamp=886448708000) 读原始数据

main Result(req=Item(type=1, timestamp=886448708000), tag=null, data=null) Item(type=1, timestamp=886448708000)

Process finished with exit code 0

相关:https://blog.csdn.net/zhangphil/article/details/150206845

相关推荐
消失的旧时光-19432 小时前
从 Kotlin 到 Dart:为什么 sealed 是处理「多种返回结果」的最佳方式?
android·开发语言·flutter·架构·kotlin·sealed
有位神秘人2 小时前
kotlin与Java中的单例模式总结
java·单例模式·kotlin
Jinkxs2 小时前
Gradle - 与Groovy/Kotlin DSL对比 构建脚本语言选择指南
android·开发语言·kotlin
&有梦想的咸鱼&2 小时前
Kotlin委托机制的底层实现深度解析(74)
android·开发语言·kotlin
golang学习记2 小时前
IntelliJ IDEA 2025.3 重磅发布:K2 模式全面接管 Kotlin —— 告别 K1,性能飙升 40%!
java·kotlin·intellij-idea
LDORntKQH2 小时前
基于深度强化学习的混合动力汽车能量管理策略 1.利用DQN算法控制电池和发动机发电机组的功率分配 2
android
冬奇Lab2 小时前
Android 15 ServiceManager与Binder服务注册深度解析
android·源码·源码阅读
2501_916008894 小时前
深入解析iOS机审4.3原理与混淆实战方法
android·java·开发语言·ios·小程序·uni-app·iphone
独行soc5 小时前
2026年渗透测试面试题总结-20(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮
常利兵5 小时前
2026年,Android开发已死?不,它正迎来黄金时代!
android