The Bug that can’t be changed, the pretense that can’t be written. The public account Yang Zhengyou now focuses on audio and video and APM, covering various fields of knowledge; Only do the whole network the most Geek public number, welcome your attention!
In memory optimization, optimizing the memory occupied by Bitmap has the most obvious effect. In Android, most OOM resources are caused by too much Bitmap resources, so the problem comes
- How to prevent bitmap from occupying too many resources and causing OOM?
- When will OOM occur on Android?
- How to build online and offline integrated memory monitoring system?
- The Drump file is too large. How can we view it online?
- Do you know how to use the tools for offline surveillance?
- What can be done about memory leaks in the Native layer?
- What efforts have you made?
- Why does MEMORY jitter cause OOM?
- What are the collection methods in memory monitoring?
After reading this article, hopefully you can use this article as an index and then solve the above problems in turn, so that you are also an expert in the field
How to get a Bitmap object?
Bitmap is one of the most important image processing classes in The Android system. Bitmap can obtain image file information, cut, rotate, scale, compress and other operations on the image, and can save image files in a specified format.
How to create a Bitmap There are two ways to create a Bitmap:
Bitmap.createbitmap () and BitmapFactory’s decode series of static methods createBitmap objects.
Below we mainly introduce BitmapFactory decode way to create Bitmap object.
Method 1. DecodeFile is loaded from the file system
- Open local images or photos with Intent
- Get the path to the image according to the URI
- Parsing by path
Bitmap bm = BitmapFactory.decodeFile(path);
Copy the code
DecodeResource is loaded from a local resource as r.drawer. XXX
Bitmap bm = BitmapFactory.decodeResource(getResources(),
R.drawable.icon);
Copy the code
DecodeStream is loaded from the input stream
Bitmap bm = BitmapFactory.decodeStream(stream);
Copy the code
DecodeByteArray loads from a byte array
Bitmap bm = BitmapFactory.decodeByteArray
(myByte,0,myByte.length);
Copy the code
2. BitmapFactory. The Options
Configure bitmapFactory. Options to prevent memory overflow, save memory overhead, and make the system more smooth
2.1 BitmapFactory.Options Parameter Description
field | The parameter name | note |
---|---|---|
inSampleSize | The sampling size | Used to load images in small size, so as not to take up too much memory, suitable for thumbnails |
inJustDecodeBounds | Whether to parse the original width and height information of the picture | While inJustDecodeBounds is true and decodeXXX is executed, BitmapFactory will only parse the original width and height of the image and will not actually load the image |
inPreferredConfig | Set the image decoding mode | Corresponding type bitmap.config. If not null, It will be used to decode the image. The default value is bitmap.config. ARGB_8888 |
inBitmap | You can save memory by using bitmaps that have been created before images are loaded | The inBitmap setting was introduced in Android 3.0. By setting this parameter, you can use the previously created Bitmap when loading images to save memory and avoid creating another Bitmap. In Android4.4, inBitmap has been added to allow inBitmap to set the size of the image to be different from the image that needs to be loaded, as long as the inBitmap image is larger than the image that needs to be loaded. |
2.2 How to compress image size
With bitmapFactory. Options, we can load the miniaturized image at a certain sampling rate, and then use the miniaturized image in ImageView. This will reduce memory usage and improve Bitamp loading performance.
This is what we call picture size compression. Dimensional compression is compressing the pixels of an image
2.3 Calculation method of memory size occupied by a picture
Calculate the memory size of a picture: picture type * width * height, change three values to reduce the memory size of the picture, prevent OOM, of course, this way may make the picture distortion.
3. How to calculate the memory size occupied by Bitmap
There are two ways to calculate the Bitmap memory size, one is to get the available Bitmap byte size bitmap.getBytecount (), the other is to get the Bitmap memory size allocated by the system bitmap.getAllocationByteCount()
4. Bitmap cache management in memory
4.1 Build the singleton cache utility class ImageCache
public class ImageCache {
private static ImageCache instance;
/ * *
* singleton class
*
* @return
* /
public static ImageCache getInstance(a) {
if (instance == null) {
synchronized (ImageCache.class) {
if (instance == null) {
instance = new ImageCache();
}
}
}
return instance;
}
}
Copy the code
4.2 Use soft reference queue to store Bitmap, disk cache and memory cache use the least use algorithm
private LruCache<String, Bitmap> lruCache;
private Set<WeakReference<Bitmap>> reusablePool;
private DiskLruCache diskLruCache;
Copy the code
4.3 LruCache algorithm stores Bitmaps
First we need to calculate the available memory size of our Android phone, and then allocate the memory to our maximum LruCache cache space. LruCache algorithm has made a series of changes between different versions
- Android 3.0 bitmaps are cached in the Native layer
- Android 8.0 Bitmap caching exists in the Java layer
- Android 8.0 Bitmap caches in the Native layer
The sizeOf the Bitmap is sizeOf, and we return getAllocationByteCount to lruCache
If the least-used cache is cleared, we plug the available cache into our reusable cache pool
Queue fetching is done through the thread pool. If the current thread is not interrupted, it removes the Bitmap from the soft reference queue and reclaims it. This ensures that the Bitmap in the queue is always the latest Bitmap
4.4 Obtaining the Sampling size inSampleSize
Getting the sample size is relatively easy; we just iterate over our reusable cache
Then check that the Bitmap meets the following criteria
- Cannot be reused before 3.0
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return bitmap.getWidth() == w && bitmap.getHeight() == h && inSampleSize == 1;
}
Copy the code
- 3.0-4.4 The width and height are the same. InSampleSize = 1
if (inSampleSize > 1) {
w /= inSampleSize;
h /= inSampleSize;
}
Copy the code
- 4.4 As long as less than or equal to
int byteCount = w * h * getBytesPerPixel(bitmap.getConfig());
// Image memory The system allocates memory
return byteCount <= bitmap.getAllocationByteCount();
Copy the code
4.5 Memory Cache Storage
public void putBitmap2Memory(String key, Bitmap bitmap) {
lruCache.put(key, bitmap);
}
Copy the code
4.6 Obtaining Memory Cache
public Bitmap getBitmapFromMemory(String key) {
return lruCache.get(key);
}
Copy the code
4.7 Disk Cache Storage
4.8 Obtaining Disk Cache
The 4.9 pixel format calculates how many bytes each pixel occupies
As mentioned earlier, ARGB_8888 is actually 4 bytes long, and the rest are 2 bytes long, so that’s how many bytes each pixel takes up by pixel format
5. Bitmap cache
5.1 LRUCache algorithm
6. Bitmap memory optimization
7.1 Disk Cache
Concept of carding
The cached content is directly written to the disk for a long time and will not disappear when the APP process dies. If not, the resource will be fetched from the network or SD card. The Lru algorithm is also used.
Encapsulation DiskLruCache
Because DiskLruCache does not provide familiar GET and PUT methods, we encapsulate DiskLruCache twice and provide get and PUT methods for external calls
7.2 Loading long Graphs
7.2.1 Points needing attention in loading long graphs
Long figure is loaded, we implement GestureDetector OnGestureListener and the OnTouchListener gestures to listen
Then Rect the local View into our BitmapRegionDecoder parameter
Let’s implement the custom View that our long graph loads
7.2.1 implementation GestureDetector OnGestureListener, the OnTouchListener interface
7.2.2 onMeasure
The width and height of the matrix are determined by the scaling factor in onMeasure
7.2.3 onScroll
In the process of gesture sliding, we should constantly determine the width and height of the sliding area, and then redraw the work
The View’s onTouch is handled directly by the long-press slide event mGestureDetector
7.2.4 ontouch
In the onDraw method, we initialize the inBitmap, set the mRect to BitmapRegionDecoder, then use the matrix to scale, and finally call Canvas. drawBitmap to View Draw, so you can perfect the local refresh effect
7.2.5 computeScroll
After sliding, we can determine the final React matrix parameters and then redraw them accordingly
Configure bitmap. Config
9. Bitmap size scaling
Different project Bitmap zoom size algorithm may not be the same, here I introduce the general zoom algorithm, in order to facilitate the knowledge of Bitmap literacy, large projects generally do not do so, interested in the commonly used picture compression framework source code
- Methods a
- Way 2