Introduction to the

Due to the specificity of Bitmaps and the memory limits that Android imposes on individual applications, such as 16MB, it is very easy to run out of memory when loading bitmaps. How to load bitmaps efficiently is an important and often overlooked problem for developers.

Caching strategy is a common idea in Android, and Bitmap is often used for caching in actual development. With caching we do not need to request images from the network or load images from storage every time. Currently, LruCache and DiskLruCache are commonly used. LruCache is often used as memory cache, while DiskLruCache is often used as storage cache. Lru is the least recently used algorithm. The core idea of this algorithm is: when the cache is nearly full, the least recently used cache target will be eliminated.

Efficient loading of Bitmaps

How do I load a Bitmap

On Android, a Bitmap is an image, which can be PNG, JPG, and other common image formats. BitmapFactory provides four classes of methods for loading bitmaps: DecodeFile decodeResource decodeStream decodeByteArray is used to load a Bitmap from the file system, resource, input stream and byte array, respectively. DecodeFile and decodeResource indirectly call decodeStream methods. These four types of methods are finally implemented at the bottom of Android, corresponding to several native methods of BitmapFactory class.

How to load a Bitmap efficiently

Core ideas: Bitmapfactory. Options is used to load images of the desired size. Bitmapfactory. Options is used to load miniaturized images at a certain sampling rate and display the miniaturized images in ImageView, thus reducing memory usage and avoiding OOM.

Options to scale the image, mainly using its inSampleSize parameter, i.e. the sampling rate. When the parameter is 1, the sampled image is the original size; when the parameter is greater than 1, for example, 2, the width and height of the sampled image is half of the original size, and the number of pixels is a quarter of the original size, and the memory size is also a quarter of the original size. When the parameter is less than 1, it has no effect and is equivalent to 1. The official documentation states that the value should always be an exponent of 2, such as 1,2,4,8,16, etc. If you pass in a non-2 exponent, the system will take the nearest exponent of 2 and replace it, but this is not valid on all Android versions and is only a suggestion.

Sampling rate

1. Set bitmapFactory. Options to true and load image 2. Remove the image’s original width and height from bitmapFactory. Options, which correspond to outWidth and outHeight arguments 3. Calculate the sampling rate inSampleSize 4 based on the rule of sampling rate and the desired size of the target View. Set bitmapFactory. Options to false to inJustDecodeBounds and reload the image

When the inJustDecodeBounds parameter is set to true, BitmapFactory will only parse the original width and height of the image, not actually load it, depending on the location of the image and the device on which the app is running. The same image in different drawable directories or the application running on devices with different screen densities can cause BitmapFactory to get different results, which is related to Android’s resource loading mechanism.

The instance

Caching strategies in Android

Cache policies include adding, obtaining, and deleting caches. LRU is one of the most commonly used caching algorithms. The idea is that when the cache is full, the least recently used cache objects are prioritized. There are two kinds of caches using LRU algorithm: LruCache and DiskLruCache, where LruCache is often used as memory cache and DiskLruCache is often used as storage cache. By combining the two, you can easily achieve a very useful ImageLoader.

LruCache

It is a generic and thread-safe class. Internally, it uses LinkedHashMap to store external cache objects as strong references. It provides get and PUT methods to obtain and add cache objects

Strong reference, soft reference, weak reference difference

Strong references: Direct object references Soft references: When only soft references exist for an object, the object will be reclaimed by gc when the system is out of memory. Weak references: When only weak references exist for an object, the object will be reclaimed by GC at any time

define

Typical initialization of LruCache (demo)



Simply provide the total sizeOf the cache and rewrite the sizeOf method. The sizeOf method calculates the sizeOf the cache object, where the size range must be in units of the total capacity. For the example code above, the total capacity is 1/8 of the current process’s available memory in KB, and the sizeOf method completes the calculation of the sizeOf the Bitmap object. Divide by 1024 to convert units into kilobytes. The getRowBytes method does the following:Return the number of bytes between rows in the bitmap's pixelsIn some cases you may also need to override LruCache’s entryRemoved method, which is called when it is cached as soon as it is removed, so some reclamation can be done in this method if needed.

Cache fetching and adding



It also supports delete operations, using the remove method to remove a specified cache object.

DiskLruCache

It is used to implement disk caching, which is achieved by writing cached objects to the file system

1. Create DiskLruCache

It cannot be created using a constructor; it provides an open method for creating itself



The first parameter saysThe disk is cached in the file system. Other specified directory path can choose SD card, specific refers to/sdcard/Android/data/package_name/cache, you can also select the data directory under the current application, the concrete can be set according to the need to be flexible. If you want to delete cached files after the application is uninstalled, select the cache directory on the SD card. If you want to keep cached data, select another specific directory on the SD card.

The second parameter indicates the version number of the application, usually 1. When the version number changes, it clears all the previous cache files, which is not very useful in real development, because the cache files will normally remain valid even if the version number of the application changes.

The third parameter represents the number of data corresponding to a single node, usually set to 1.

The fourth parameter indicates the total size of the cache, for example, 16MB. When the cache exceeds this size, some caches are cleared to ensure that the total size does not exceed this value

Typical creation process

GetDiskCacheDir suspected to have been removedIf the SD card exists or cannot be removed, the getExternalCacheDir() method is called to get the cache path, otherwise the getCacheDir() method is called to get the cache path. Is the first access to the/sdcard/Android/data / / cache the path, while the latter is access to the/data/data / / cache the path. Finally, the retrieved path is concatenated with a uniqueName and returned as the final cache path. UniqueName is a unique value that can be used to distinguish between different types of data, such as bitmap, file, etc.

2. Add the cache of DiskLruCache

The addition is done through the Editor, which represents an edit object for the cache object. If the cache is being edited, edit() returns null, meaning that DiskLruCache does not allow editing a cache object at the same time. The reason why the URL is converted into a key is that there may be special characters in the URL of the image, which will affect the use of THE URL in Android. Generally, the MD5 value of the URL is used as the key.

You can get the Editor object by turning the url of the image into a key. For this key, if no other Editor object currently exists, Edit() returns a new Editor object through which to get a file output stream. Since the previous Open1 method set a node to have only one data, the DISK_CACHE_INDEX constant below can be set to 0

There is a file output stream, but images downloaded from the network can be written to the system file through this file output stream

After the above steps, commit the write through Editor’s commit(). If the image download fails, Editor’s Abort () can be used to roll back the entire operation.

3.DiskLruCache cache lookup

The cache lookup process also requires the URL to be converted into a key, and then the DiskLruCache get method is used to obtain a Snapshot object, which is then used to obtain the cached file input stream, and then the Bitmap object. In order to avoid OOM, it is not recommended to load the original image directly. But loading a scaled image through bitmapFactory.options is problematic for FileInputStream scaling because it is an ordered file stream, and two decodeStream calls affect the position properties of the file stream. The second decodeStream was null. In order to solve this problem can be got through file stream it corresponds to the file descriptor, then through BitmapFactory. DecodeFileDescriptor method to load a picture of a resized.