Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use Glide's LruCache

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article introduces the knowledge of "how to use Glide's LruCache". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

Usage and results

Import the Glide library directly into the project and call the internal LruCache to see the effect.

LruCache lruCache = new LruCache (2); lruCache.put ("1", 1); lruCache.put ("2", 2); lruCache.put ("1", 1); lruCache.put ("3", 3); System.out.println (lruCache.get ("1")); System.out.println (lruCache.get ("2")); System.out.println (lruCache.get ("3"))

Briefly explain the contents of the code, create a storage space with space 2 (without revealing the internal structure here), store the data with the put () method, and then fetch each data through get (), and then look at the results.

Oh, my God! 2 gone? What's going on here? In order to know the answer, we have to go to the Glide library to see why.

LruCache source code guide

First of all, let's take a look at what little guys there are in LruCache's variable family.

Public class LruCache {/ / Bidirectional linked list private final Map cache = new LinkedHashMap (100,0.75f, true); private final long initialMaxSize; / / initialize maximum capacity private long maxSize; / / maximum capacity private long currentSize; / / existing capacity}

Similarly, for LruCache, like HashMap, there are only three steps to go, so I will explore LruCache from these three steps, but let's start with a question: what is the role of initialMaxSize?

New LruCache

Public LruCache (long size) {this.initialMaxSize = size; this.maxSize = size;}

If you want to come here, the reader already knows the routine, and initializes the maximum capacity and maximum capacity, so go straight to the next step.

Put (key, value)

Public synchronized Y put (@ NonNull T key, @ Nullable Y item) {/ / the return value is a 1 final int itemSize = getSize (item); / / if 1 is greater than or equal to the maximum value, there is no action / / which means that size cannot be set to 1 if (itemSize > = maxSize) {/ / reserved method for rewriting onItemEvicted (key, item); return null. } / / An if (item! = null) {currentSize + = itemSize;} @ Nullable final Y old = cache.put (key, item); if (old! = null) {currentSize-= getSize (old); if (! old.equals (item)) {onItemEvicted (key, old);}} evict () / / 1-- > return old;} / / method private void evict () {trimToSize (maxSize) called directly by comment 1; / / 2-- >} / / method protected synchronized void trimToSize (long size) {Map.Entry last; Iterator cacheIterator called directly by comment 2 }}

This is a locking mechanism to determine whether our data needs to be deleted by judging the current capacity and the maximum capacity. But the question remains, what is the role of initialMaxSize? what we can know is that maxSize is a value used to control the size of capacity.

Get ()

Public synchronized Y get (@ NonNull T key) {return cache.get (key);}

So this is a call to the data in LinkedHashMap, but still does not say the role of initialMaxSize.

About initialMaxSize

I won't buy it here, because in fact, from my point of view, this initialMaxSize is really useless. Ha! However, it is used in another place.

Public synchronized void setSizeMultiplier (float multiplier) {if (multiplier)

< 0) { throw new IllegalArgumentException("Multiplier must be >

= 0 ");} maxSize = Math.round (initialMaxSize * multiplier); evict ();}

That is, it is used to control our maximum capacity, but I think it is still useless, but I am too lame. This method has no other method to call it. It is a method that we use directly in the process of using it. It may be related to a problem such as saving data many times. In a scene, it is also similar to Glide's image cache load. I also hope that readers who know can give me an answer.

LinkedHashMap

Because the mode of operation is the same as that of HashMap, it will not be repeated, just look at what his nodes look like.

Static class LinkedHashMapEntry extends HashMap.Node {/ / has front and back nodes, which is what we call bi-directional linked lists LinkedHashMapEntry before, after; LinkedHashMapEntry (int hash, K key, V value, Node next) {super (hash, key, value, next);}}

But here, I have another question: why don't I see the movement of the whole data? That is, the recently used data should be switched to the last starting position, where on earth did he deal with it? Make a guess, since it is the use of put () to cause the transformation of the data in the two-way linked list, then we should need to enter the LinkedHashMap.put () method to query.

Of course, for readers who are interested in exploring, I need to remind you that this call cannot directly query put (), which will only call an interface function, or an abstract class function. The most appropriate method is to use our breakpoint to explore the query.

But after a period of effort, constantly in-depth invocation to explore and discover such a problem, he will eventually call such a problem.

/ / Callbacks to allow LinkedHashMap post-actions void afterNodeAccess (Node p) {} / / move the data to the last bit void afterNodeInsertion (boolean evict) {} void afterNodeRemoval (Node p) {}

This is before we learned about HashMap and did not find a few methods, and it is clearly written that it is reserved for LinkedHashMap. Whoa! Then our operation must be in these.

/ /-- > call to the following method near line 656 of the HashMap source code / / there is an afterNodeAccess (e) inside the putVal () method; / /-- > LinkedHashMap implements it / / pushes the current data directly to the last location / / that is, it becomes the recently used data void afterNodeAccess (Node e) {/ / move node to last LinkedHashMapEntry last If (accessOrder & & (last = tail)! = e) {LinkedHashMapEntry p = (LinkedHashMapEntry) e, b = p.before, a = p. Null; if; p.after = null; if (b = = null) head = a; else b.after = a If (a! = null) a.before = b; else last = b; if (last = = null) head = p; else {p.before = last; last.after = p;} tail = p; + + modCount }}

Well, from then on, we know the transformation process of the whole linked list.

Actual combat: hand-playing LruCache

This is a very tense and exciting link, let's look for ideas before we play with the code.

(1) what are the storage containers used? Because the idea of LinkedHashMap is too lengthy, we use arrays to rebuild the whole code.

(2) the shift of existing variables involved in the key call methods put (), get (), and put ().

WOW! It seems that there is not so much to be done, so let's take a look at the framework constructed for the first time.

Public class LruCache {private Object objects []; private int maxSize; private int currentSize; public LruCache (int size) {objects = new Object [size]; maxSize = size } / * insert item * @ param item * / public void put (Object item) {} / * get item * @ param item * / public Object get (Object item) {return null Shift the following array * @ param index * / public void move (int index) {}} according to the subscript correspondence

Because there is a shift as long as it is an array transformation, the shift operation is essential. Well, our job now is to fill in the data and how to operate the corresponding shift.

Public class LruCache {public Object objects []; private int maxSize; public int currentSize; public LruCache (int size) {objects = new Object [size]; maxSize = size;} / * * insert item * * @ param item * / public void put (Object item) {/ / when the capacity is not full, it is divided into two cases / / 1. There is / / 2 in the container. Int index = search (item) does not exist in the container; if (index = =-1) {if (currentSize)

< maxSize) { //容器未满,直接插入 objects[currentSize] = item; currentSize++; } else { // 容器已满,删去头部插入 move(0); objects[currentSize - 1] = item; } }else { move(index); } } /** * 获取item * * @param item */ public Object get(Object item) { int index = search(item); return index == -1 ? null : objects[index]; } /** * 根据下标对应,将后续数组移位 * * @param index */ public void move(int index) { Object temp = objects[index]; // 将后续数组移位 for (int i = index; i < currentSize - 1; i++) { objects[i] = objects[i + 1]; } objects[currentSize - 1] = temp; } /** * 搜寻数组中的数组 * 存在则返回下标 * 不存在则返回 -1 * @param item * @return */ private int search(Object item) { for (int i = 0; i < currentSize; i++) { if (item.equals(objects[i])) return i; } return -1; } 因为已经真的写的比较详细了,也没什么难度的撸了我的20分钟,希望读者们能够快入入门,下面给出我的一份测试样例,结束这个话题。

That's all for "how to use Glide's LruCache". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report