Many apps have user systems, whether they are implemented by themselves or by third parties, they probably need to display user avatars. In more common scenarios, avatars will appear in certain lists, such as contact lists, message lists, etc. Although avatars are also images, we have higher requirements for avatars than ordinary pictures. The original avatar image may have various sizes, but in the App, we may need a fixed style of avatar, such as square or circle. If we use general image caching tools such as SDWebImage, Kingfisher, etc., we also need to crop and process the image ourselves. If we directly use UIImageView to reduce the size, the image details will become too "sharp" and affect the viewing experience. Furthermore, an App may have more than one avatar style. For example, some scenes require large avatars, some require small avatars, and some require original-size avatars; or some scenes require square avatars, and some scenes require rounded-rectangle avatars, and so on. Note: Simply using layer.cornerRadius or CALayer to mask will cause sliding performance issues in the list, so it is not considered. If we want to optimize, we certainly hope that these small avatars of different styles can be stored locally, without having to obtain them from the network and then cut or process the styles. This will reduce unnecessary traffic consumption and increase the speed of avatar loading, which will naturally improve the user experience. Based on the above analysis, we will design an avatar cache system. Its goal is to quickly obtain and cache styled avatar images and integrate them into existing projects more easily. Some prerequisites: The image URL of the avatar is unique, that is, different avatars have different URLs. If the user changes the avatar, the new avatar URL will be different from the old one; Okay, let's play a thinking game. First, the existing user model may be:
avatarURLString represents the remote avatar link. If we want to download it, the simplest way is to use a constructor of NSData:
If there are 5 items in a list, all of which are generated by the same user, and the user's avatar needs to be displayed 5 times at the same time, do we have to download it 5 times? To solve this problem, we can treat the act of getting the avatar as a "request":
We can record the requests in an array (i.e. request pool):
In this way, every time you want to download an avatar, construct a request, put it into the request pool first, and then check the number of requests in the request pool that contain this avatarURLString. If the number is greater than 1, it means that there has been a same request before, and we will not perform the download operation, and quietly wait for the help of the first request. Navi AvatarPod After a while, the previous request download is finished, then you only need to execute the completion of all requests with the same avatarURLString, and the last one (or several) will get the service "for free". Navi Completion The above is the first time you need to download. If we have already downloaded the avatar image, we can still construct the request, but we will not perform the download operation, but search in the file system. Similarly, our request can include styles. If the five avatars of the same user have different styles, we only need to process the styles separately when executing the completion of each request. Since you need to save it after downloading, what is the best way to save it? Some people prefer to use the file system API to store data directly in the file system; some people already use Core Data, so they will prefer to put it in Core Data. Moreover, some attribute types of Core Data entities have External properties. After checking, they do not take up memory space and avoid the tediousness of directly operating the file system; some people use Realm or directly use SQLite, etc. Anyway, there are similar storage processes, but the details are different. My suggestion is to save the original image in the file system (or check External in Core Data), and small styled avatars can be saved directly in the database as attributes (usually Core Data or Realm support NSData attributes, but they cannot be too large because they will stay in memory). Unfortunately, if we were to create a framework to cache avatars now, we would not be able to help users store files in a very specific way. Because the details vary so much, it is really hard to take care of them all. And even if we have one, it is difficult for users to integrate this step into existing code. If we do not consider user preferences, then what we actually make is a "general" image caching system. General here means "not optimized enough". Fortunately, we can define a protocol, declare the storage API in the protocol, and let users implement the storage process by themselves. Our cache system only needs to call the API and does not need to care about the details of the storage process. Taking the avatar style into consideration, we have:
A brief explanation: URL naturally represents the original link of the avatar; style represents the style of the avatar to be displayed this time, which will be discussed further later; placeholderImage is easy to understand. Before displaying the real avatar, a placeholder is needed. Different apps have different designs, so it is also left to the user; localOriginalImage represents the original image stored locally. Since the storage is controlled by the user, the reading is naturally controlled by the user; localStyledImage represents the local styled avatar, which the user can provide according to different styles; the last is saveOriginalImage(originalImage:styledImage:), the storage process is controlled by the user, including the original image and the styled image this time. Among them, the avatar style can be made as follows:
There are original styles (no processing), fixed-size rectangles (can generate squares, etc.), rounded rectangles with transparent edges (can generate circles, etc.), and a free style, where the user provides the image transformation function. It looks quite complete and can be increased. Then we extend a method to UIImageView:
For the convenience of users. ***The diagram is as follows: Navi's cache architecture The user has a list to display, and the list items contain avatars, so a description of the Avatar is constructed to wake up the Avatar in the AvatarPod. AvatarPod avoids repeated downloads and implements the entire logic. For example, it first searches the memory cache. If it is not found, it checks whether the user has provided a local image. If not, it downloads it. After the download is complete, it processes the style and gives the original image and the style image to the user for storage. Then in the specific integration, users only need to let their User implement the Avatar protocol or construct a new "intermediate object" that contains User and AvatarStyle, and let this object implement the Avatar protocol. I recommend using the intermediate object method, which will require less modification to the existing code and better support multiple styles. Please see Navi's code and demo for details. There are not many files, so it should be easy to understand. However, to run the demo, you need to log in to a Twitter account in "Settings" on your iOS device. If you don't have a Twitter account, you can register one at twitter.com. ***, the name Navi comes from the Na'vi in the movie "Avatar", which are intelligent humanoid creatures on the planet Pandora. After humans arrived on Pandora, they used genetic modification to synthesize a creature similar to the Na'vi that can be controlled by humans, that is, Avatar (meaning incarnation or substitute), in order to better communicate with the original Na'vi. Original link: https://github.com/nixzhu/dev-blog |
[[127002]] Three elements for Baidu's success...
I only dare to smile at you Not because of polite...
Springs are clear and sweet because they have a c...
Just like the never-ending "sweet and salty&...
1. Click cheating Click fraud is a relatively low...
Rumor: "Eating unblanched spinach can cause ...
This painting, in bright green, makes the whole r...
When a search engine enters a web page, it will b...
Does your boss not understand your job? This arti...
In the past few days, news about the test of Chin...
Xiaomi, which was only founded in 2010, has now g...
Real SEO is to adopt reasonable means that are ea...
Video of a car accident involving an M5 high-perfo...
"Freshwater" means water that does not ...
After the emergence of Kuaishou short video, shor...