zoukankan      html  css  js  c++  java
  • 【转载】基于AFNetWorking3.0的图片缓存分析

    原文出处: Yasin的简书

    理论

    不喜欢理论的可以直接跳到下面的Demo实践部分

    缓存介绍

    缓存按照保存位置可以分为两类:内存缓存、硬盘缓存(FMDB、CoreData…)。
    我们常说的网络请求缓存包含内存缓存、硬盘缓存和URL缓存。

    图片缓存思路

     
    图片缓存流程图.png

    URL缓存

    网络请求除了客户端需要做简单的配置外,最主要需要服务器支持,服务端也很简单,只需要在response里面设置Cache-Control字段就行了.

    最常见的URL缓存实现方式:NSURLCache。NSURLCache可以在memory 和 disk 上缓存。
    AFNetWorking是基于NSURLSession(iOS7以上的网络请求框架),在生成配置的时候有三种配置选择

    也就是说default同时实现了内存缓存和硬盘缓存,ephemeral实现了内存缓存,对于图片下载我们当然选择default。
    我们还可以对缓存的大小进行设置,只需要对NSURLCache进行初始化就可以了

    实现初始化

    -application:didFinishLaunchingWithOptions:中对[NSURLCache sharedURLCache]进行初始化设置:

    也可以单独对NSURLSessionconfiguration进行设置,
    在AFNetWorking中对于图片网络请求设置了20M的内存缓存和150M的硬盘缓存:

    缓存策略

    缓存策略是指对网络请求缓存如果处理,是使用缓存还是不使用

    在AFNetWorking中同样对configuration进行设置

    如果你继承AFImageDownloader重新实现了他的初始化,requestCachePolicy注意AFImageDownloader中只有三种才设置了缓存

    内存缓存

    AFNetWorking3.0放弃了NSCache作为图片内存缓存管理,这让我非常不解。
    有人说它的性能和 key 的相似度有关,如果有大量相似的 key (比如 “1”, “2”, “3”, …),NSCache 的存取性能会下降得非常厉害,大量的时间被消耗在 CFStringEqual() 上,不知这是不是放弃使用NSCache的原因。

    像素在内存中的布局和它在磁盘中的存储方式并不相同。考虑一种简单的情况:每个像素有R、G、B和alpha四个值,每个值占用1字节,因此每个像素占用4字节的内存空间。一张1920*1080的照片(iPhone6 Plus的分辨率)一共有2,073,600个像素,因此占用了超过8Mb的内存。但是一张同样分辨率的PNG格式或JPEG格式的图片一般情况下不会有这么大。这是因为JPEG将像素数据进行了一种非常复杂且可逆的转化。

    AFNetWorking3.0的图片缓存类貌似是基于这个理论来做内存大小管理的(之前AF的内存大小计算方法有错,我修改了一下提交了,现在已经审核通过合并进去了,哈哈哈哈哈,我也算是贡献过AF了)。AFNetWorking2.x中还是使用AFImageCache进行memory上缓存。

    NSCache在memory上缓存,类似于NSMutableDictionary ,以 哈希算法 管理。有自动清理机制,当缓存到memory时,如果memory空间不够,则会自动删除memory中当前界面不使用的空间。

    AFAutoPurgingImageCache使用NSMutableDictionary 进行内存缓存映射,并进行管理,当内存警告时就清空NSMutableDictionary。如果内存占用超过限制,则按照时间顺序进行删除。

    硬盘缓存

    就是我们常说的把数据保存在本地,比如FMDB,CoreData,归档,NSUserDefaults,NSFileManager等等,这里就不多说了。
    图片缓存建议使用NSFileManager,因为一般图片data会比较大,测试证明路径缓存会比放在数据库有更高的性能。

    实践

    Demo下载

    使用NSURLSession做网络请求缓存。

        NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];     //使用default配置,自带网络请求缓存
        [config setHTTPAdditionalHeaders:@{@"Accept":@"image/*"}];//设置网络数据格式
        NSURLSession *session = [NSURLSession sessionWithConfiguration:config];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        WEAKSELF
        NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { //使用’获取数据(NSURLSessionDataTask)‘的方式发起请求
            UIImage *image = [UIImage imageWithData:data];
            dispatch_async(dispatch_get_main_queue(), ^{
                weakSelf.imageView.image = image;
            });
        }];
        [task resume];
    

    使用AFNetWorking下载图片

    导入头文件#import "UIImageView+AFNetworking.h"
    使用:[imageView setImageWithURL:url];
    UIImageView+AFNetworking做了内存缓存,和基于NSURLSession的网络请求缓存

    代码分析:

    测试

    使用Charles查看图片下载的网络请求发生了几次,判断缓存是否成功。
    其中硬盘缓存需要写入时间,网络请求完成后略等一下,否则硬盘缓存不会生效

    设置默认网络缓存大小

    如果没有对NSURLRequestURLCache进行设置,默认是使用[NSURLCache sharedURLCache],所以如果有需要可以如下设置

  • 相关阅读:
    [汇编] 基础知识
    最长回文子串(1)
    整数分解为2的幂
    位数阶乘
    change log
    SEO简介
    http请求过程
    ES6新增特性——Promise
    rem在移动端的应用
    js截取字符串操作slice、substring 、substr
  • 原文地址:https://www.cnblogs.com/cleven/p/5468137.html
Copyright © 2011-2022 走看看