iOS_设计实现一个异步图片下载工具

最近阅读学习了SDWebImage源码。参照其思路实现了一个极简的版本。下面主要是描述一下各个模块的实现思路和需要注意的细节。

项目地址:HYLWebImage


一、图片下载类的实现思路

  1. 客户端通过URL向服务器请求图片,通过苹果NS类的网络请求异步加载
  2. 将返回的image放在UIImageView控件上展示
  3. 使用NSURLSession或者NSData来下载

需要注意的点:

  • 异步请求成功后切换到主线程(参考了SDWebImage的主线程宏)
#define dispatch_main_async_safe(block)\
if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) {\
        block();\
    } else {\
        dispatch_async(dispatch_get_main_queue(), block);\
    }

复制代码
  • block闭包的使用
  • 多添加对非正常值的判断
  • 请求超时的解决策略
  • 请求的优先级

二、线程管理类的实现思路

  1. 维护两个队列:
    • 下载队列
    • 预下载队列
  2. 根据max值的大小来确定Downloader进入哪个队列,限制最大并发量。max值可开放为接口,便于自定义
  3. 需要在各种状态下(比如完成了一个Downloader)判断下载队列的值是否 < max && 预下载队列是否有值,如果都是true,则把预下载队列的Downloader移入下载队列

需要注意的点:

  • manager类需要通过单例只初始化一次,保持一个全局状态
  • Downloader根据条件加入哪一个队列
  • 下载队列发生变化后,检查一次条件(max和预下载队列的值)

三、缓存类的实现思路

  1. 下载完后将图片放入内存;
  2. 将最大缓存的数量和是否不使用缓存开放为接口,便于自定义(暂不从图片大小考虑)
  3. 提供本地文件读写的方法
  4. 根据runtime,动态的存入内存
  5. 优先存入内存,超过的最大值则存入本地
  6. 优先从内存读取,没有则才从本地读取
  7. 从本地存储读取的数据时,如果当前最大内存数没有满,则放入内存

需要注意的点:

  • 与线程管理类的交互,主要是在线程管理类里适当的位置写入和读取
  • 内存设计需要考虑的问题:
    • 内存存储的空间大小,避免内存压力过大
    • 与上一条对应的,需要有删除淘汰策略
      • 以队列的方式删除:先进先出
      • LRU算法:比如30分钟内是否被使用过(最近最久未使用算法)
        • 每次读写时遍历检查
        • 前后台切换时遍历检查
        • 如果上次使用时间和当下时间超过三十分钟,那么移除图片
  • 本地存储需要考虑的问题:
    • 读取效率要比内存低,要有存储方式的选择
    • 尽管空间相对大,但也要有大小的限制
    • 本地存储的淘汰删除策略:
      • 超过几天后是否删除

四、UIImageView分类的实现思路

  • 在UIImageView的分类里调用Manager管理类即可
  • 分类的变量用runtime的关联变量实现
  • 把一个downloader下载类存入关联变量,在一个下载周期进行删除和添加操作,避免多个下载任务

五、总体的实现思路

核心流程是manager这样一个管理类来调度downloader下载类和cache缓存类。当一个任务开始,manager管理类先检查是否有内存缓存,然后再检查是否有本地缓存。如果有则用缓存的图片,如果没有,就调用downloader下载,下载成功后,再放入缓存,最后显示图片。

六、还没有做的功能

  • 图片解码和压缩功能
  • URL的合法性校验
  • 检查是否有还未完成的下载
  • …………

七、补充一个对图片解码实现时的注意点

  • 对不同格式的图片,解码采用不同的方法,这就是需要应用设计模式里的【策略模式】
  • 在哪个阶段做图片解码处理,这涉及到职责分工的问题
    • 从本地存储读取后,解码
    • 网络请求返回后,解码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值