SDWebImage的原理实现机制,如何解决TableView卡的问题?
- 入口setImageWithURL:placeholderImage:options:会先把placeholderImage显示,然后SDWebImageManager根据URL开始处理图片。
- 进入SDWebImageManager-downloadWithURL:delegate:options:userInfo:,交给SDImageCache从缓存查找图片是否已经下载queryDiskCacheForKey:delegate:userInfo:.
- 先从内存图片缓存查找是否有图片,如果内存中已经有图片缓存,SDImageCahceDelegate回调imageCache:didFindImage:forKey:userInfo:到SDWebImageManager。
- SDWebImageManagerDelegate回调webImageManager:didFinishWithImage:到UIImageView+WebCache等前端展示图片。
- 如果内存缓存中没有,生成NSInvocationOperation添加到队列开始从硬盘查找图片时否已经缓存。
- 根据URLKey在硬盘缓存目录下尝试读取图片文件。这一步是在NSOperation进行的操作、所以回主线程进行结果回调notifyDelegate:。
- 如果上一操作从硬盘读取到了图片,将图片添加到内存缓存中(如果空闲内存过小,会先清空内存缓存)。SDImageCacheDelegate回调imageCache:didFindImage:forKey:userInfo:。进行回调展示图片。
- 如果从硬盘缓存目录读取不到图片,说明所有缓存都不存在该图片,需要下载图片,回调imageCache:didNotFindImageForKey:userInfo:。
- 共享或重新生成一个下载器SDWebImageDownloadManager开始下载图片。
- 图片下载由NSURLConnection来做,实现相关delegate来判断图片下载中,下载完成和下载失败。
- connection:didReceiveData:中利用ImageIO做了按图片下载进度加载效果。
- connectionDidFinishLoading:数据下载完成后交给SDWebImageDecoder做图片解码处理。
- 图片解码处理在一个NSOperationQueue完成,不会拖慢主线程UI。如果有需要对下载的图片进行二次处理,最好也在这里完成,效率会好很多。
- 在主线程notifyDelegateOnMainThreadWithInfo:宣告解码完成,imageDecoder:didFinishDecodingImage:userInfo:回调给SDWebImageManager告知图片下载完成。
- 通知所有的downloadDelegates下载完成,回调给需要的地方展示图片。
- 将图片保存到SDImageCache中,内存缓存和硬盘缓存同时保存。写文件到硬盘也在以单独NSInvocationOperation完成,避免拖慢主线程。
- SDImageCache在初始化的时候z会注册一些消息通知,在内存警告或退到后台的时候清理内存图片缓存,应用结束的时候清理过期图片。
- SDWI也提供了UIButton+WebCcache和MKAnnotationView+WebCache,方便使用。
- SDWebImagePrefetcher可以预先下载图片,方便后续使用。
- 如何解决tableView卡顿问题,前面也提了很多方案。通过设置最大并发数,设置当前页的cell,而不是把所有cell一次性设置完,以及数据图片的三级缓存,直接保存在内存中和沙盒缓存中进行读取,降低网络请求的次数,不仅节约用户流量,也会保证tableView滑动的流畅性。
SDWebImage怎样实现图片的缓存机制的?
- 图片的缓存,内存缓存、沙盒缓存、操作缓存,以TableViewController为例:
- 每次cell需要显示,都需要重新调用-(UITbaleViewCell *)tableView:(UITableView *)tabeView cellForAtIndexPath:(NSIndexPath *)indexPath{}方法
- 每次调用tableView显示行的数据源方法时,如果需要从网络加载图片,就需要将加载图片这样的韩式操作放在子线程上执行,从网络下载的图片可以以键值对的形式保存在定义的可变字典中,将每张图片的唯一的路径作为键,将从网络下载下来的图片作为值,保存在内存缓存中,这样每次滑动tableViewcell重用时就直接判断内存缓存中有没有需要的图片,如果有就不需要再次下载,在没有出现内存警告或者程序员手动清理内存缓存时,就直接从内存缓存中获取图片。
- 为了每次退出程序,再次进入程序时,不浪费用户的流量,需要将第一次进入程序时加载的图片保存在本地沙盒缓存文件中,在沙盒中保存的图片数据没有被改变之前,下次开启程序就直接从本地沙盒的缓存文件中读取需要显示的图片,并将沙盒缓存文件夹(Cache)中保存的图片保存到内存缓存中,这样用户每次滑动tableView cell重用时直接从内存缓存中读取而不是从沙盒中读取,节约时间。
网友评论