美文网首页iOS 开发学习成长之路征服iOSIOS技术精华
SDWebImage 引发的 cell不断下拉引起的闪退 卡顿

SDWebImage 引发的 cell不断下拉引起的闪退 卡顿

作者: 陈雨尘 | 来源:发表于2016-06-01 15:35 被阅读1239次

    最近在我们的项目中出现了一个问题,暴力测试 高速上拉cell 不断加载出更多的cell  就会出现app 闪退。调试的时候 会发现 高速拉出很多cell的时候 内存 会有极大的浮动,拉出差不多200多个cell的时候就会出现闪退。为了弄清楚是怎么回事,我查了很多资料 ,也看了很多国外的博客 ,后来终于让我发现了问题所在,废话不多说 ,听我细细道来

    1.首先是SDwebimage的原理:



    UIImageView+WebCache:setImageWithURL:placeholderImage:options:先显示 placeholderImage ,同时由SDWebImageManager 根据 URL 来在本地查找图片。

    SDWebImageManager:downloadWithURL:delegate:options:userInfo:SDWebImageManager是将UIImageView+WebCache同SDImageCache链接起来的类, SDImageCache:queryDiskCacheForKey:delegate:userInfo:用来从缓存根据CacheKey查找图片是否已经在缓存中

    如果内存中已经有图片缓存, SDWebImageManager会回调SDImageCacheDelegate :imageCache:didFindImage:forKey:userInfo:

    而 UIImageView+WebCache 则回调SDWebImageManagerDelegate:webImageManager:didFinishWithImage:来显示图片。

    如果内存中没有图片缓存,那么生成 NSInvocationOperation 添加到队列,从硬盘查找图片是否已被下载缓存。

    根据 URLKey 在硬盘缓存目录下尝试读取图片文件。这一步是在 NSOperation 进行的操作,所以回主线程进行结果回调notifyDelegate:。

    如果上一操作从硬盘读取到了图片,将图片添加到内存缓存中(如果空闲内存过小,会先清空内存缓存)。SDImageCacheDelegate 回调imageCache:didFindImage:forKey:userInfo:。进而回调展示图片。

    如果从硬盘缓存目录读取不到图片,说明所有缓存都不存在该图片,需要下载图片,回调imageCache:didNotFindImageForKey:userInfo:。

    共享或重新生成一个下载器SDWebImageDownloader开始下载图片。

    图片下载由 NSURLConnection 来做,实现相关 delegate 来判断图片下载中、下载完成和下载失败。

    connection:didReceiveData:中利用 ImageIO 做了按图片下载进度加载效果。

    connectionDidFinishLoading:数据下载完成后交给SDWebImageDecoder做图片解码处理。

    图片解码处理在一个 NSOperationQueue 完成,不会拖慢主线程 UI。如果有需要对下载的图片进行二次处理,最好也在这里完成,效率会好很多。

    在主线程notifyDelegateOnMainThreadWithInfo:宣告解码完成,imageDecoder:didFinishDecodingImage:userInfo:回调给 SDWebImageDownloader。

    imageDownloader:didFinishWithImage:回调给 SDWebImageManager 告知图片下载完成。

    通知所有的 downloadDelegates 下载完成,回调给需要的地方展示图片。

    将图片保存到 SDImageCache 中,内存缓存和硬盘缓存同时保存。

    写文件到硬盘在单独 NSInvocationOperation 中完成,避免拖慢主线程。

    如果是在iOS上运行,SDImageCache 在初始化的时候会注册notification

    到 UIApplicationDidReceiveMemoryWarningNotification 以及

    UIApplicationWillTerminateNotification,在内存警告的时候清理内存图片缓存,应用结束的时候清理过期图片。

    SDWebImagePrefetcher可以预先下载图片,方便后续使用。更详细的可以 转

    http://www.open-open.com/lib/view/open1409822188744.html 



    2.整个过程都看似非常的完美,内存处理的也非常好,为什么还会出现问题呢,问题所在的地方就

    这个方法是下载图片之后 做的一些处理

    是对下载的图片进行重绘,从而带到压缩的作用,这个方法很好 大大的减少了因为图片太大而引起的内存暴增,但是问题也来了,大量下拉cell 不断调用

    从而不断的调用这个压缩的方法  就会导致内存 极具增大  但 sd 自带的释放内存的方法  缺不能触发 ,导致app 闪退


    3.解决办法就是

    这个属性 ,关闭这个属性就可以了    


    这个属性是控制其是否压缩的   关闭这个属性即可  😄


    关闭这个属性就可以了,但是 也会带来 内存 增高的 问题  ,只是这样带来的内存增高是可以让VC捕捉到的  ,这个 内存 是因为缓存了 大量的图片引起的 

    所以在收到内存警告的时候清除缓存就可以了 。好了  至此这 问题就解决了。

    分享我的经验希望能帮到大家 如有不对之处 请大家多多指教。 联系qq 719967870

    相关文章

      网友评论

      • 33ecdd9d5d72:写的很好
        陈雨尘:@辰貃 谢谢
      • 嘿晴天:我关闭压缩了貌似闪退的更快了,我看到滑动的时候不会内存暴增,是cpu 暴增
      • justtobebetter:谢谢啊 这个问题我搞了两天0.0
      • 陈雨尘:这就是一个折中的方法 至于是否 适合 自己 要自己 测试哦
      • Zhxuuuu:关闭压缩的话,拖拽时给imageView赋值会卡顿,最好不要这样做
      • brance:楼主 问你一下因为我只想应用到某个页面 ,一般这个属性在哪里关闭最好,,哪里打开最好了。
        陈雨尘:@Brance 进去这个 页面 关闭 退出这个页面 再 打开
      • 燕燕爱涛涛:亲爱的 棒棒哒 你是我的男神 :kissing_heart:

      本文标题:SDWebImage 引发的 cell不断下拉引起的闪退 卡顿

      本文链接:https://www.haomeiwen.com/subject/sgvflttx.html