用Glide扩展图片加载,使其支持阿里云的OSS访问

本文介绍了一种解决方案,即如何在Glide中集成阿里云OSS服务以支持oss格式URL的图片加载。该方案涉及自定义ModelLoader、DataFetcher及工厂类,并通过@GlideModule注解注册组件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    公司有款产品使用了阿里云的服务。

    在之前的版本中,手机明文持有Key,拿到Key后可以进行上传操作。上传结束将返回的url(http开头)上传给服务器,服务器进行保存。

    这本来是个正常的逻辑,但是在后面我们遇到了搞鬼的,他拿到了Key并且开始上传黄色图片。

    这时我们需要进行方案二,用户不持有key,登陆之后才能从服务器拿到key,并且key是有有效期限的,需要定时获取。服务器负责与阿里云进行key的交互。上传之后我们拿到的不再是以http开头的url(http://xxxx.jpg),而是一个以oss开头的后面跟着一段字符串的url(oss://xxxssdddfffggg)。服务器的图片地址也已这个形式保存

    很安全的样子对不对。而且关键是,阿里云已经帮我们做好了上传下载的功能。哇,好方便。但是,这跟原有的图片访问不兼容啊。Glide只支持url,resource等访问,oss开头是阿里云才支持的格式,如何解决呢。

    首先我们想到的是自己实现了个图片三级缓存,并且在调用阶段,根据字符串开头判断是用普通的网络请求还是用阿里云的sdk。功能实现了,而且效果不错。但是几天写出来的框架,会有Glide那么大的工程性能好吗。持着这样的怀疑,我决定模仿Glide的框架去优化我的框架。

    写着写着发现了ModelLoader这个类。发现不一般,打开文档查看发现它支持我们扩展访问类型。不错,我们来实现一下。

 

####9月27日更新####

以下均为kotlin实现

    1.首先ModelLoader这个类就是Glide用来针对不同地址头使用不同加载方式产生的。Glide需要根据地址头来调用对应的加载方式。这个加载方式就是DataFetcher,这里先实现DataFetcher。

import xxx.aliyun.AliyunOssClient
import com.bumptech.glide.Priority
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.data.DataFetcher
import java.io.InputStream

class AliyunOSSDataFetcher(private val model: String) : DataFetcher<InputStream> {
    val ossClient = AliyunOssClient()
    override fun getDataClass(): Class<InputStream> {
        return InputStream::class.java
    }

    override fun cleanup() {
    }

    override fun getDataSource(): DataSource {
        return DataSource.REMOTE
    }

    override fun cancel() {
        ossClient.cancel()
    }

    override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {

        ossClient.download(model, object : AliyunOssClient.LoadCallback {
            override fun onLoadComplete(inputStream: InputStream) {
                callback.onDataReady(inputStream)
            }

            override fun onLoadFailed(exception: Exception) {
                callback.onLoadFailed(exception)
            }

        })

    }
}

    这里的ossClient在Glide调用loadData时,需要下载图片,并把结果通过callback返回给Glide。ossClient的具体实现就不具体写了,可以根据阿里云的文档进行实现,主要是返回inputStream给callback.onDataReady()

    2.然后是ModelLoader

import com.bumptech.glide.load.Options
import com.bumptech.glide.load.model.GlideUrl
import com.bumptech.glide.load.model.ModelLoader
import com.bumptech.glide.load.model.ModelLoader.LoadData
import java.io.InputStream
class AliyunOSSModelLoader : ModelLoader<String, InputStream> {
    override fun buildLoadData(model: String, width: Int, height: Int, options: Options): LoadData<InputStream>? {
        return LoadData<InputStream>(GlideUrl(model), AliyunOSSDataFetcher(model))
    }

    override fun handles(model: String): Boolean {
        return model.startsWith("oss:")
    }
}

    这里就很明显了,是给Glide判断用的,如果是oss:开头,那么久用AliyunOssDataFetcher加载

    3.然后是实现一个ModelLoaderFactory

import com.bumptech.glide.load.model.ModelLoader
import com.bumptech.glide.load.model.ModelLoaderFactory
import com.bumptech.glide.load.model.MultiModelLoaderFactory
import java.io.InputStream

class AliyunOSSModelLoaderFactory :ModelLoaderFactory<String,InputStream> {
    override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader<String, InputStream> {
        return AliyunOSSModelLoader()
    }

    override fun teardown() {

    }
}

    4.最后一步,给Glide加载注释@GlideModule,让其生成配置

import android.content.Context
import xxx.utillib.image.glide.AliyunOSSModelLoaderFactory
import xxx.utillib.util.FileUtil
import com.bumptech.glide.Glide
import com.bumptech.glide.GlideBuilder
import com.bumptech.glide.Registry
import com.bumptech.glide.annotation.GlideModule
import com.bumptech.glide.load.engine.cache.DiskLruCacheFactory
import com.bumptech.glide.load.engine.cache.LruResourceCache
import com.bumptech.glide.module.AppGlideModule
import java.io.InputStream

@GlideModule
class CustomGlideModule : AppGlideModule() {
    override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
        registry.prepend(String::class.java, InputStream::class.java, AliyunOSSModelLoaderFactory())
    }

    override fun applyOptions(context: Context, builder: GlideBuilder) {
        super.applyOptions(context, builder)
        var defaultMemoryCacheSize = 8 * 1024 * 1024L
        val runtimeMemoryCacheSize = Runtime.getRuntime().maxMemory() / 8
        val defaultDiskCacheSize = 250 * 1024 * 1024L
        if (runtimeMemoryCacheSize > defaultDiskCacheSize) {
            defaultMemoryCacheSize = runtimeMemoryCacheSize
        }
        builder.setMemoryCache(LruResourceCache(defaultMemoryCacheSize))
                .setDiskCache(DiskLruCacheFactory(FileUtil.get().getCachePath(context, FileUtil.Companion.CacheCategory.PICTURE), defaultDiskCacheSize))

    }
}

    至此大家应该可以实现了

 

此实例是基于上一篇 九宫格切图 实例开发,九宫格切图完成了从图库选择图片,点击按钮切割出九张图片,并保存在图库里,拼图游戏切图后,可以不用保存到图库里,这里改为保存到分布式目录下,实现跨设备文件访问。 游戏介绍 九宫格拼图游戏,作为一种经典的益智游戏,其游戏规则主要围绕在3×3的方格盘上,通过移动八块拼图(其中一个格子为空),最终将拼图全部归位至正确位置。以下是九宫格拼图游戏规则的详细解释: 游戏目标 将八块拼图在3×3的方格盘上正确排列,使得每行、每列都填满,且没有拼图重叠或遗漏。 游戏准备 准备一个3×3的方格盘,其中八个位置放置拼图,剩下一个位置留空作为移动空间。 游戏技巧 从外围开始:由于外围的拼图更容易移动和归位,因此玩家可以从外围的拼图开始入手,逐步向中心推进。 利用空格:空格是移动拼图的关键所在,玩家需要巧妙地利用空格来创造移动的机会和条件。 观察与预判:在移动拼图之前,玩家需要仔细观察整个方格盘的布局和拼图的位置关系,并预判移动后的结果和可能产生的影响。 游戏规则 初始布局:游戏开始时,八块拼图在方格盘上随机分布,留有一个空格作为移动区域。 移动规则: 玩家每次只能移动一个拼图,且只能将其移动到与其相邻的空格中(上下左右四个方向)。 拼图不能跳过其他拼图直接移动到更远的空格,也不能斜向移动。 归位要求: 玩家需要通过一系列的移动,将八块拼图逐一归位到正确的位置上,使得整个方格盘呈现出一个完整的图案或数字序列(根据不同的游戏版本而定)。 在归位过程中,玩家需要不断观察并思考最佳的移动策略,以减少移动次数并避免陷入无法解开的局面。
最新发布
06-09
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值