SDWeb Image Loading Display GIF and Performance Problems
Prior to SDWebImage 4.0, GIF diagrams could be displayed using UI Image View. If SDWebImage 4.0 does the same, it will only show static images. SDWebImage 4.0 uses FLAnimated Image View to display GIF diagrams through FLAnimated Image. The two libraries in this article are SDWebImage 4.0.0 and FLAnimatedImage 1.0.12, respectively.
CocoaPods Installation
pod 'SDWebImage' pod 'SDWebImage/GIF'
General usage
Display GIF with FLAnimated Image View instead of UI Image View. Uses introduced in README.md of FLAnimatedImage
FLAnimatedImage *image = [FLAnimatedImage animatedImageWithGIFData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"https://upload.wikimedia.org/wikipedia/commons/2/2c/Rotating_earth_%28large%29.gif"]]]; FLAnimatedImageView *imageView = [[FLAnimatedImageView alloc] init]; imageView.animatedImage = image; imageView.frame = CGRectMake(0.0, 0.0, 100.0, 100.0); [self.view addSubview:imageView];
Don't write that, this code will block the main thread! The main thread obtains NSData through the URL and waits until the download is complete to execute the next step.
FLAnimatedImage View is similar to UIImage View in that it initializes, sets frame s, adds to views, and assigns values to image attributes to display static images; unlike FLAnimatedImage, it assigns values to animatedImage attributes to display dynamic images. The problem with the above code is the generation of FLAnimatedImage.
SDWebImage adds an asynchronous loading method of GIF to FLAnimatedImage View, just like asynchronous loading of static images.
imageView.sd_setImage(with: url, placeholderImage: placeholder)
If a small amount of GIF is displayed, it should be possible to write in this way. However, if you need to show a large number of GIFs with UITableView or UICollection View, there may be performance problems and a stuck when sliding.
Improving performance
To improve performance, you can specify RunLoopMode, animate in default mode, and stop animation in tracking mode (such as scroll view sliding).
imageView.runLoopMode = RunLoopMode.defaultRunLoopMode.rawValue
In my code, there will still be a Dunka. Looking at the source code of SDWebImage, we found the problem.
sd_setImage(with:placeholderImage:) calls sd_internalSetImageWithURL: method
Note that the setImageBlock parameter in the sd_internalSetImageWithURL: method generates FLAnimatedImage here. Further look at sd_internalSetImageWithURL: Implementation of the method
The macro definition dispatch_main_async_safe(block) guarantees that the block is executed in the main thread, which contains setImageBlock. So setImageBlock is executed in the main thread, that is to say, FLAnimatedImage is generated in the main thread. This step is time-consuming, blocking the main thread and causing the Dunka.
The solution is to put the generation of FLAnimatedImage in a sub-thread. SDWebImage source code can be modified directly, but this is not recommended. A better way is to add methods to FLAnimated Image View
extension FLAnimatedImageView { func setImage(with url: URL?, placeholderImage: UIImage?) { sd_internalSetImage(with: url, placeholderImage: placeholderImage, options: SDWebImageOptions(rawValue: 0), operationKey: nil, setImageBlock: { [weak self] (image, imageData) in // Enter global queue DispatchQueue.global(qos: .userInteractive).async { [weak self] in guard self != nil else { return } let imageFormat = NSData.sd_imageFormat(forImageData: imageData) if imageFormat == .GIF { // Create FLAnimatedImage in global queue let animatedImage = FLAnimatedImage(animatedGIFData: imageData) DispatchQueue.main.async { [weak self] in guard let strongSelf = self else { return } // Set image in main queue strongSelf.animatedImage = animatedImage strongSelf.image = nil } } else { DispatchQueue.main.async { [weak self] in guard let strongSelf = self else { return } // Set image in main queue strongSelf.image = image strongSelf.animatedImage = nil } } } }, progress: nil, completed: nil) } }
Also call sd_internalSetImageWithURL: method, just modify the setImageBlock parameter, create FLAnimatedImage in the sub-thread, and then set the picture in the main thread.
Calling this method is simple
imageView.setImage(with: url, placeholderImage: placeholder)
In this way, the UITableView slides smoothly.
The code has been uploaded to GitHub: https://github.com/Silence-GitHub/GIFDemo
For reprinting, please indicate the source: http://www.cnblogs.com/silence-cnblogs/p/6682867.html