Sdwebimage High Quality source code reading notes (both the latest and older versions are available)

Source: Internet
Author: User
Latest Source Update:

SD External API has not changed, but the internal packaging and logic has some small changes, the recent yykit also all analyzed again, because before also looked at SD, look back has changed, and then analyze the latest

Notes:

Validoperationkey---> [self class]
Sdoperationdictionary---> Mount to uiview control via category Runtime

Internal Storage sdwebimagecombinedoperation (here's an operation Cacheoperation to store the cache)

Latest Call Order

1. Common Method-(void) Sd_setimagewithurl: (Nullable nsurl *) URL placeholderimage: (Nullable uiimage *) placeholder

2.SDWebImageManager Single Instance Call

-(Nullable ID <SDWebImageOperation>) Loadimagewithurl: (Nullable nsurl *) URL
                                              options: (sdwebimageoptions) Options
                                             Progress: (Nullable Sdwebimagedownloaderprogressblock) Progressblock
                                            completed: (Nullable Sdinternalcompletionblock) Completedblock;
Manage's two simple
@property (strong, Nonatomic, ReadOnly, nullable) Sdimagecache *imagecache;//Processing Cache
@property ( Strong, Nonatomic, ReadOnly, nullable) Sdwebimagedownloader *imagedownloader; Processing Network Downloads

2.1 Manage the above method is initialized below

2.2 Sdimagecache------> Slow Deposit Cases

Operation.cacheoperation = [Self.imagecache querycacheoperationforkey ... ] Level Two cache lookup method, returning the queue to the cache field assigned to Operation

2.2.1 Memory Cache Nscache Disk cache FileManager File Store returns regardless of whether it is found or not, except that the image is empty

2.3 sdwebimagedownloader-------> Download a single example (Urloperations this field to store the downloaded action)
call [[Self.imagedownloader Downloadimagewithurl ...] based on the lookup after the action callback Querycache above.

2.3.1 Call Addprogresscallback The block under this method is the 2.3.2 sdwebimagedownloaderoperation for creating the sdwebimagedownloaderoperation download queue *o Peration = self. Urloperations[url]; According to the URL, no words to call the above block to create a download queue return 2.3.3 Return Sdwebimagedownloadtoken object contains URLs (for key queries) and Downloadoperationcanceltoken store back When the block (complete and progress) 2.3.4 is created, Nsoperationqueue adds the created task, and then calls start (requires rewriting) for downloading, proxy callback, receiving data 2.3.5 nsurlsess Ion Didreceivedata return image

2.4 Return to the Sdwebimagemanager block level two cache memory and disk cache (the cache here is the default of 7 days, the application to the background will be cached cleanup)

3. Callcompletionblockforoperation calls the final block callback to the user UI control for assignment


Foreshadowing: Every time you call the outer API will call cancel method, the principle of the blog has been introduced, here to say how the specific is achieved.


First: The UI layer API below calls the Sd_internalsetimagewithurl core method for downloading
[Self sd_setimageloadoperation:operation forkey:validoperationkey];
The returned sdwebimagecombinedoperation and UI controls are category mounted here


Second: Sdwebimagemangae invokes Loadimagewithurl initialization sdwebimagecombinedoperation
The object's cacheoperation is a sdimagecache call that directly returns Nsoperation assignment (canceling the cache operation)
The bottom of the code also added a block operation.cancelblock = ^{to cancel the operation of the Loadoperation network download;


Finally: Sd_cancelimageloadoperationwithkey call cancellation
@interface Sdwebimagecombinedoperation:nsobject <SDWebImageOperation> has implemented cancel agent
Finally call sdwebimagecombinedoperation inside the cache field to cancel the caching operation, call Cancelblock cancel the network download

Some of the core logic has not changed, but the implementation of the way has changed, read it before, and now see it again very soon, familiar friends can see it by themselves



Update: Sdwebimagedecoder is used to decompress images (principles and why)

SD Internal has helped us to request back data or cached to the local image resources are asynchronous decompression, so do not need us to do, simple to understand

Picture Compression Process

Suppose we use the +imagewithcontentsoffile: method to load a picture from a disk, the picture is not uncompressed at this time, and then the generated uiimage are assigned to the Uiimageview; then an implicit catransaction captures the Uiimageview layer tree changes; When the next run loop of the main thread arrives, the Core Animation submits the implicit transaction, which may copy the image and be affected by factors such as whether the image is byte-aligned, the CO The PY operation may involve some or all of the following steps: allocating memory buffers to manage file IO and decompression operations, reading file data from disk to memory, decoding compressed picture data into uncompressed bitmap forms, which is a time-consuming CPU operation; last Core Animation using uncompressed Bitmap data to render the Uiimageview layer.

In the previous steps, we mentioned that the image decompression is a very time-consuming CPU operation and that it is executed by default in the main thread. So when you need to load more pictures, it will have a serious impact on the responsiveness of our application, especially in the fast sliding list, the problem will be more prominent.

Click on the open link to pick up the blog of the Arrogant God, you need to go in detail to see.


Personal Understanding:

1. First, PNG and JPEG are images of the compression format, PNG is lossless compression, support Alpha,jpeg lossy, optional 1-100 compression ratio

2. For example, you have a PNG image of 20B, then your corresponding image binary data is 20B, the uncompressed image can be hundreds of thousands of B

3. The specific formula is the pixel width * pixel high * each pixel corresponds to the byte

4. Then when you do the image rendering, you must get the extracted raw pixel data, in order to do graphics rendering, which is the reason for the decompression


SD in Sdwebimagedecoder This file in the forced decompression, we assign value to ImageView is already uncompressed file, so will not card main main thread, otherwise the default is in the main thread for decompression, a picture of a lot of cards exploded



Peacetime projects used in the library quite a lot, did not seriously see a few, to their own plan this year to read sdwebimage,afnetworking, have time to yykit components also see, although only so a few, I feel reading these can learn a 1% code logic, I was satisfied with , recently spent a week on the internet to read the Sdwebimage source analysis and SD itself code logic analysis, each added a note, after all, this is the first step to go, after reading it again, accidentally saw a map on the internet, coupled with their own understanding, think this picture is too suitable, the interpretation of a very complete

Above picture source




This figure is divided into four parts, after listening to my analysis you can basically understand


First, the function of all the classes of SD is simply introduced

3.8.1 version of the role of all classes to introduce

Nsdata+imagecontenttype image data to determine the format of the current picture


The Sdimagecache cache defines Disk and memory level two cache (Nscache) to manage cache single cases


SDWEBIMAGECOMPAT guarantee macro definition and inline picture scaling for compatibility of different platforms/versions/screens


Sdwebimagedecoder picture uncompressed, only one interface inside


Sdwebimagedownloader Asynchronous Picture Download management, manage download queues, manage Operation management Network request processing results and exception single cases

The block that holds the callback to the network request itself understands that the data structure is probably

structure {"url": [{"Progress": "Progressblock"},{"complete": "Completeblock"}]}


Sdwebimagedownloaderoperation implementation of the asynchronous download picture nsoperation, network request to give nsurlsession agent download

A custom Operation task object that requires manual implementation of the start Cancel method


Sdwebimagemanager core Management class mainly encapsulates the main interface of cache management + Download management Downloadimagewithurl simple


The Sdwebimageoperation operation protocol only defines the proxy for the downloaderoperation on the cancel operation interface.


Sdwebimageprefetcher in the case of low priority to download pictures in advance, simple encapsulation of sdwebimageviewmanager is rarely used


mkannotationview+webcache– load pictures for Mkannotationview asynchronously


Uibutton+webcache load pictures for UIButton asynchronously


Uiimage+gif converts image data to a specified format picture


Uiimage+multiformat converts image data to a specified format picture


Uiimageview+highlightedwebcache load pictures for Uiimageview asynchronously


Uiimageview+webcache load pictures for Uiimageview asynchronously


Uiview+webcacheoperation Save the current mkannotationview/uibutton/uiimageview asynchronous download picture operations


Read the basic look like this, it does not matter, continue to look down, the final will give a complete summary


Look at the basic operation diagram of the core class


A sketch of your own flowers, to see the work.




OK, we're going to go through the logic step-by-step according to the code we called.


1. First step (external control)

Direct call to SD-exposed methods

__weak typeof (self) weakself = self;
    [Self.imageview sd_setimagewithurl:[nsurl urlwithstring:@ "http://cdn.duitang.com/uploads/item/201111/08/ 20111108113800_wycvp.thumb.600_0.jpg "] Placeholderimage:nil completed:^ (uiimage *image, NSError *error, Sdimagecachetype CacheType, Nsurl *imageurl) {
       
        if (image && CacheType = = Sdimagecachetypenone)
        {
            WeakSelf.imageView.alpha = 0;
            [UIView animatewithduration:1.0f animations:^{
               
                weakSelf.imageView.alpha = 1.f;
            }];
        }
        else
        {
            weakSelf.imageView.alpha = 1.0f;
        }
        
    }];
This is very simple, we often use, when using the SD opportunity to play a series of methods, this series of methods will eventually be converted into

[Self sd_setimagewithurl:url placeholderimage:placeholder options:options progress:nil Completed:completedBlock];


2. Step Two (Uiimageview + webcache)

All of the above methods of invocation, which are eventually entered into this method for picture loading//URL loading Pictures///placeholder for bitmap/options download pictures of various fancy settings are generally used by sdwebimageretryfailed | Sdwebimagelowpriority-(void) Sd_setimagewithurl: (nsurl *) URL placeholderimage: (uiimage *) placeholder options: ( Sdwebimageoptions) Options Progress: (Sdwebimagedownloaderprogressblock) Progressblock completed: ( Sdwebimagecompletionblock) Completedblock {//Cancel the current download operation if not canceled, then when the TableView slide, the current cell ImageView will always go to download the picture, and then first display the download
    
    Finished picture, direct disorder [self sd_cancelcurrentimageload]; {...... Omit a section of code//determine if (URL) {...
        Omit a section of code} __weak __typeof (self) wself = self; Key class Sdwebimagemanager to process picture downloads//downloads three levels 1 current manager call download 2 get from cache, hit failed with Sdwebimagedownloader object call Download 3.SDWebImageDow Nloaderoperation finally uses the inheritance//Nsoperation object Nsurlsession method to download the picture, the agent inside carries on the Operation ID <SDWebImageOperation> operat Ion = [Sdwebimagemanager.sharedmanager downloadimagewithurl:url options:options progress:progressblock completed:^ ( UIImage *image, NSERror *error, Sdimagecachetype CacheType, BOOL finished, Nsurl *imageurl) {[Wself removeactivityindicator];
            if (!wself) return;
                Dispatch_main_sync_safe (^{if (!wself) return;
                Set the Sdwebimageavoidautosetimage default does not add UIImage to the Uiimageview object, and placed in the Conpleteblock to the caller to deal with themselves, make a filter or fade in or out what
                    if (Image && options & sdwebimageavoidautosetimage) && Completedblock) {
                    Completedblock (image, error, cachetype, URL);
                Return
                    else if (image) {wself.image = image;
                [Wself Setneedslayout]; else {if ((Options & Sdwebimagedelayplaceholder)) {wself.image = place
                        Holder
                    [Wself Setneedslayout]; }//Here is the final callback out of block if (COMPletedblock && finished) {Completedblock (image, error, cachetype, URL);
        }
            });
        }]; Save this operation if multiple picture requests can be used to cancel//cancel the current Uiimageview download task and then save Operations//That is, when the key value in the dynamically bound dictionary corresponds A picture download a single picture value array is 0, otherwise it is multiple, download will be based on key removed [self sd_setimageloadoperation:operation forkey:@ "Uiimageviewimageload"]
    ;
            else {Dispatch_main_async_safe (^{[self removeactivityindicator]; The IF (completedblock) {nserror *error = [Nserror errorwithdomain:sdwebimageerrordomain code:-1 UserInfo:@{N
                Slocalizeddescriptionkey: @ "trying to load a nil url"}];
            Completedblock (nil, error, sdimagecachetypenone, URL);
    }
        }); }
}
Analysis under:

This is the first way to call Cancel, and why is this ... Explain the bugs that will occur

The cell that is normally displayed on the screen is like this, and when the network is unstable, the first cell is still requesting data, and the user is slipping directly



There will be the following state, this is the TableView simple diagram, when the cell after the list is ready to load, will be found in the reuse pool, and some words directly out, then reuse the cell inside the pool or the first cell pointed to the ImageView pointer, If you do not stop the previous network request, then it is very scary to take it out and then request it based on the data binding later. The reason is that if you do not cancel the previous request, the principle of ImageView is to first display the latest download after the picture, it will immediately show, so be sure to first cancel the


Here's another example:

A imageview requested two pictures, 1.png and 2.png, but we only want to show 2.png, so we need to cancel the 1.png request. The reasons for this are two points:
1. In the asynchronous request (the sequence is uncertain), it is possible that 1.png will be acquired after 2.png, will overwrite the 2.png
2. Reduce network request, network request is a very time-consuming operation


The point of this step, then, is to enable the Sdwebimagemanager admin to invoke his method for network requests

-(ID <SDWebImageOperation>) Downloadimagewithurl: (nsurl *) URL
                                         options: (sdwebimageoptions) Options
                                        Progress: (Sdwebimagedownloaderprogressblock) Progressblock
                                       



3. Step Three (Sdwebimagemanager)

This management class has two right-hand men.

One is Sdimagecache specifically manages caching

A:nscache is responsible for the memory cache, which is basically the same as Nsdictionary

B: Disk caching is done using Nsfilemanager write files

Note:

1. Nscache has the function of automatic deletion to reduce the memory consumed by the system and to set the memory critical value

2. The Nscache is thread-safe and does not need to be added to the lock;

3. Key objects are not replicated as they are in nsmutabledictionary. (the key does not need to implement the Nscopying protocol).

Looking for pictures from Imagecache//Every time you ask Sdwebimagecache for a picture, you first check whether there is a corresponding picture in the memory according to the key value of the picture URL, if there is a direct return; if not, go to the hard drive in Ioqueue. Where the filename is based on the MD5 value generated by the URL, the image is first cached in memory, then the picture is returned:-(Nsoperation *) Querydiskcacheforkey: (NSString *) key done: (
    Sdwebimagequerycompletedblock) Doneblock {if (!doneblock) {return nil;
        } if (!key) {Doneblock (nil, sdimagecachetypenone);
    return nil; 
    //First check the In-memory cache ...//1. Go to the memory level to find uiimage *image = [self imagefrommemorycacheforkey:key];
        if (image) {Doneblock (image, Sdimagecachetypememory);
    return nil; //If not found in memory//2. If it is not in memory, look it up on the disk.
    If found, it is placed in the memory cache and calls the Doneblock callback nsoperation *operation = [nsoperation new];
        Dispatch_async (Self.ioqueue, ^{if (operation.iscancelled) {return; //Create an automatic release pool, free of memory//if your application or thread is to run for a long time and it is possible to generate a large number of autoreleased objects, you should use Autorelease pool blocks @autore
     Leasepool {//from hard drive, got it. Memory is stored according to the field       UIImage *diskimage = [self diskimageforkey:key]; if (diskimage && self.shouldcacheimagesinmemory) {//pixel nsuinteger cost = Sdcache
                Costforimage (DiskImage);
            Cache to Nscache [Self.memcache setobject:diskimage forkey:key cost:cost];
            } dispatch_async (Dispatch_get_main_queue (), ^{doneblock (DiskImage, Sdimagecachetypedisk);
        });

    }
    });
return operation; }

Small Knowledge Points:

Here open the asynchronous serial queue to find in disk, to ensure that the main thread is not blocked, and opened the Autoreleasepool to reduce the memory surge problem, can be released in time, if you can get, first cached in memory and then callback


If you don't get a picture in memory or on a disk, you'll have another manager's sdwebimagedownloader to download the picture

A: This is also a single example, is responsible for downloading pictures of the download are placed in the Nsoperationqueue completed

The final method of downloading a picture-(ID <SDWebImageOperation>) Downloadimagewithurl: (nsurl *) URL Options: (Sdwebimageoptions) Options Progress: (Sdwebimagedownloaderprogressblock) p
    Rogressblock completed: (sdwebimagecompletionwithfinishedblock) Completedblock {
    {......}
    
    Generating the corresponding key based on the URL does not have special processing for [self absolutestring] nsstring *key = [self cachekeyforurl:url]; The previous operation. The main processing is as follows://1. Determine the legality of the URL//2. Create Sdwebimagecombinedoperation object//3. See if the URL is a failed download before//go to Imagecache to find pictures operation.cacheoperation = [Self.imagecache querydiskcacheforkey:key done:^ (U Iimage *image, Sdimagecachetype cachetype) {if (operation.iscancelled) {@synchronized (Self.runningo
            perations) {[Self.runningoperations removeobject:operation];
        } return; ///If the picture is not found or sdwebimagerefreshcachedDownload pictures from the network if (!image | | options & sdwebimagerefreshcached) && (![ Self.delegate respondstoselector: @selector (imagemanager:shoulddownloadimageforurl:)] | | [Self.delegate imagemanager:self Shoulddownloadimageforurl:url])
                    {if (Image && options & sdwebimagerefreshcached) {Dispatch_main_sync_safe (^{ If the picture exists in the cache, but the options or sdwebimagerefreshcached notify cache to refresh the cached picture Completedblock (IM
                Age, Nil, cachetype, YES, URL);
            });
            //Set download option properties {...} Open Download//Here are the two callbacks are from the downloaderoperation inside Out, Progressblock is not taken, directly in the outermost call place to deal with, the completion of the words need to be cache, so here to deal with the callback, processing and then back to Pull out ID <SDWebImageOperation> suboperation = [Self.imagedownloader downloadimagewithurl:url options:downl
       Oaderoptions progress:progressblock completed:^ (uiimage *downloadedimage, NSData *data, NSError *error, BOOL finished) {         The upper is weak here set to strong to avoid being released __strong __typeof (weakoperation) strongoperation = weakoperation;  if (!strongoperation | | strongoperation.iscancelled) {//Do nothing If the operation is cancelled//#699 for more details//If we would call T He completedblock, there could is a race condition between this block and another for the Completedblock object, so I
                    F This one is called second, we'll overwrite the new data} else if (error) { If an error occurs, the call completes the callback and puts the URL in the download foiled URL array dispatch_main_sync_safe (^{if (str Ongoperation &&!strongoperation.iscancelled) {completedblock (nil, error, Sdimagecach
                        Etypenone, finished, URL);
                    
                    }
                    }); if (Error.code!= NsurlerRornotconnectedtointernet && error.code!= nsurlerrorcancelled &am p;& error.code!= nsurlerrortimedout && error.code!= F && error.code!= nsurlerrordatanotallowed && Error.code
                        != nsurlerrorcannotfindhost && error.code!= nsurlerrorcannotconnecttohost) {
                        @synchronized (self.failedurls) {[Self.failedurls addobject:url]; }} else {//When the download is available, so long to take him from the previous F Ailurl Remove if ((Options & sdwebimageretryfailed)) {@synchronized (SELF.FA
                        Iledurls) {[Self.failedurls removeobject:url]; }
                    }
                    //Is the hard disk cache BOOL Cacheondisk =!
                    
                    (Options & Sdwebimagecachememoryonly);  if (Options & sdwebimagerefreshcached && image &&!downloadedimage) {//image Refresh hit the Nsurlcache cache, do isn't call the completion block} else if (Dow Nloadedimage && (!downloadedimage.images | | (Options & Sdwebimagetransformanimatedimage))
                        
                        && [self.delegate respondstoselector: @selector (ImageManager:transformDownloadedImage:withURL:)]) {
                        Parallel processing of a picture's cache in a global queue//first convert to a picture, which is implemented by the proxy object The image is then cached for processing dispatch_async (Dispatch_get_global_queue dispatch_que Ue_priority_high, 0 ^{uiimage *transformedimage = [Self.delegate imagemanager:self transfor Mdownloadedimage:downloadedimage WIThurl:url]; if (Transformedimage && finished) {

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.