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

相关推荐
shughui2 小时前
APP、Web、H5、iOS与Android的区别及关系
android·前端·ios
千里马学框架2 小时前
敏感权限如何自动授权?pkms的permission部分常用命令汇总
android·车载系统·framework·perfetto·权限·系统开发·pkms
a2591748032-随心所记3 小时前
android14 google默认进程、apk、hal、以及service等
android
明天…ling3 小时前
四天学习笔记
android
小六花s3 小时前
渗透测试前四天PHP文件包含笔记
android·学习·渗透测试
Rubin智造社3 小时前
见路不走:从《天幕红尘》读懂2026年的创新密码
android·开发语言·kotlin
冷雨夜中漫步4 小时前
Python入门——__init__.py文件作用
android·java·python
学习3人组4 小时前
采用EVENT定时任务同步视图到物理表提升视图查询效率
android
followYouself4 小时前
ViewPager+Fragment
android·前端