Almost any modern application can not do without downloading images from the network and we,
Surfingbird , is no exception. However, you can not just upload pictures sequentially, because if the user rewinds a couple of screens, he will have to wait until the previous images are loaded, which are no longer needed.
Therefore, to increase the responsiveness of the application and reduce the waiting time of the user, we have applied several techniques, which we want to tell about now.
It should be noted that many people use lazy loading of pictures. This is a great practice, we love and respect it. This saves traffic and memory on the phone. However, in order to take care of the memory, it is important not only to organize the proper storage of downloaded images, for example, the forcing cache, but also to optimize the loading itself.
Despite the fact that in the modern world, users have long been unlimited Internet and traffic is not a problem, the waiting time for downloading images is still critical. Users are very impatient, they do not want to wait for the download, they want to sniff-sniff-sniff and we give them this magic.
Take the case when an application is a collection of pictures. What will the developer who does not think about the responsiveness of the application? He will take all the pictures, put them in the download queue and it turns out that they will be loaded, on average, one after the other.
See what it could look like.
')
What do we see? The user has to wait until the previous pictures are loaded.
In this case, the user does not see that something happens at all. Now for the user, the application slows down, and all because there is no way to understand whether the picture is loaded or not.
It is important that the user has an understanding that everything is fine, everything is loading, a little more and a picture will appear. The first thing we did was add a progress bar to the loading of the picture. Implementing this is easy: add a subview to our picture and change the progress of the callback:
And we register downloadProgressBlock operations (for operations inherited from AFURLConnectionOperation):
[imageView.af_imageRequestOperation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { weakSelf.progress = totalBytesRead/totalBytesExpectedToRead; }];
That's what comes out of it.
Despite the fact that waiting for the download of the picture is the same as in the first case, in the end, the user has the feeling that everything is fine.
But this is not ideal at all. As you can see from the example, if the user rewinds quite far away, then the wait for downloading a picture will be very long. So why not show in the first place what is on the screen right now?
To download each image we use NSOperation. As soon as we receive the next portion of content, we create a download operation for each image and place it in a queue with a medium priority. As soon as the picture is in sight - we set the operations for its loading to high priority, and it is this picture that loads before those that we do not need now.
There is one more subtlety - most likely, that those pictures that the user has scrolled are less necessary for him than those that are below. Therefore, as soon as the picture disappears from the screen, we set the operations for downloading it to a priority even lower than the priority of operations for preloading.
- (void) willAppear { [self.af_imageRequestOperation setQueuePriority:NSOperationQueuePriorityVeryHigh]; } - (void) willDisappear { [self.af_imageRequestOperation setQueuePriority:NSOperationQueuePriorityVeryLow]; }
As a result, we managed to increase the responsiveness of the application and reduce the user’s waiting time. Visually, the application has become faster.
If you think that such tricks do not work, we advise you to read this
Facebook study.
Do you use something like that? It will be nice to discuss in the comments.