(原创博客,如将转载烦请备注出处)
第一次写技术博客,咱们直入主题。
SDWebImage我相信很多iOS开发者都用过、用到甚至项目中仍在使用,SDWebImage的基本原理是
1.开辟异步子线程(这里是用的GCD)进行图片的下载工作;
2.下载完成后通过block回调,将回调回来的图片image进行内存缓存和磁盘缓存;
3.显示图片时会优先去内存缓存中查找,有即显示,无则去磁盘缓存内进行查找,有则显示,无即进行1中的下载操作
而这篇文章需要提及并深入运用以上三点,因此这篇文章其实相当于带你读懂SDWebImage源码。
新浪微博iOS客户端看图,未缓存过的图片会出现一个具有透明度的圆形,在此圆形当中有一个白色扇形在随着图片的加载不断扩大面积,当扇形扩大至圆形时该图片加载完成即可显示大图。
而该扇形什么时候显示多少面积由该图片已下载字节与总字节的比值决定,so接下来咱们先看SDWebImage的下载原理,block之间如何调用与回调。
首先SDWebImage源码全程使用的是block,以下截图可以看出SDWebImage熟练运用block的正向调用
通过调用sd_setImageWithURL方法进入到UIImageView的WebCache这个category的sd_setImageWithURL方法,然后调用downloadImageWithURL这个block进入到SDWebImageManager如下图
由上图可以看到首先通过queryDiskCacheForKey该方法检索内存缓存和磁盘缓存是否存在,存在即block回调并删除该operation,不存在缓存即进行下一步操作,同样是调用downloadImageWithURL方法,但此处调用的是SDWebImageDownloader的downloadImageWithURL方法,如下图
通过调用initWithRequest方法进入到最终的boss环节,即真正的下载操作
跳转到SDWebImageDownloaderOperation这个类里面,SDWebImage用的是URLSession的dataTask进行下载,其实这个也同样适用具有下载功能的应用中,所以SDWebImage相当于给iOS的下载做了一个demo
每次的下载任务开始,该方法只会被调用一次,self.expectedSize即是该图片的data数据总字节,咱们要保存下来留到后面用到
该方法会被多次调用,直到self.imageData.length == self.expectedSize。可以由上图看到计算已下载数据字节与总字节的比值,用self.ratio保存,后面要回调回去
此处是我修改源码的第一处,加了一个回调参数ratio
此处下载完成调用该方法,无误的情况下会发送SDWebImageDownloadFinishNotification这个通知
并且会进行completionBlock(image, self.imageData, nil, YES);的回调,
由以上步骤依次调用相应方法进入到相应的类里进行相应操作,回调反之。当image回调至SDWebImageManager时调用SDImageCache进行图片的缓存
在UIImageView+WebCache.h中咱们能拿到这个下载完成百分比了,接下来就是动画代码,核心代码都在这个category内。
以上全是个人理解,如有偏颇欢迎指正。
最后,我通篇看下来也觉得有点文不对题,头重脚轻的感觉,大家轻喷,还是直接下载代码运行看看吧。