Using BitmapFactory to parse simple analysis of Bitmap, bitmapfactory
Simple Analysis of Bitmap Using Different BitmapFactory Methods
I believe that Bitmap has been used during Android development.
In fact, Google also has a simple article about how Bitmap is used, Manage Bitmap Memory. Here we will introduce some simple Bitmap memory optimizations.
In fact, I wrote this article because I recently wrote a control that involves a lot of Bitmap displays, but because there are too many images, if it is completely displayed, it will lead to OOM, therefore, an image cache must be created,
Now I have more than 800 images of the 136px * PX size in my hand. Now I am storing the images in the disk files, assets directories, and drawable directories respectively, to test the performance of creating images through BitmapFactory.
The test platform is a Preview-GoogleNexus6-5.1.0-API22-1440x2560 on the Genymotion simulator.
The maximum size of image multiplexing is 1/8 of the memory size of the current application.
The code for reading Bitmap is no longer put. It is quite easy to use BitmapFactory methods to read Bitmap code.
The test results are as follows:
| Performance |
File |
Assets |
Drawable |
Drawable-ldpi |
Drawable-mdpi |
| Total read time |
1360 |
406 |
2550 |
4100 |
2545 |
| Maximum number of images in the same memory |
181 |
181 |
15 |
9 |
15 |
| Generate image size |
136*128 |
136*128 |
476*448 |
635*597 |
476*448 |
|
Drawalbe-hdpi |
Drawable-xhdpi |
Drawable-xxhdpi |
Drawable-xxxhdpi |
|
| Total read time |
1479 |
1132 |
940 |
619 |
|
| Maximum number of images in the same memory |
34 |
60 |
134 |
237 |
|
| Generate image size |
317*299 |
238*224 |
159*149 |
119*112 |
|
As can be seen from the table above, for the same set of images, the size of memory taken from file, assets, and drawable and the time consumed are not the same, in general, the Assets Directory provides the fastest retrieval speed and consumes less memory.
The larger the size of the image taken from the drawable directories, the larger the memory usage and the longer the reading time.
We carefully observe the methods in BitmapFactory, and we will find that, whether it is decodeResource or decodeFile, they will finally call the decodeStream method to obtain the Bitmap object.
For obtaining bitmap from files and assets objects, the only difference between them is reading from a local disk and reading from assets. For an application, reading speed is faster, so we can understand it.
Why are the sizes of images in the drawable directory different?
I remember Google once said on the official Android developer website
If your application's minSdkVersion is 4 or greater, you do not need default drawable resources when you provide alternative drawable resources with the screen density qualifier. even without default drawable resources, Android can find the best match among the alternative screen densities and scale the bitmaps as necessary. however, for the best experience on all types of devices, you shoshould provide alternative drawables for all three types of density.
The general meaning of this sentence is that for an application whose minimum sdk version is 4, if we have provided a drawable resource in a certain drawable path, therefore, we do not need to provide default Resources in the default drawable directory (you must have a default configuration item for xml files such as values and layout, and drawable is enough if you have one ). The Android system automatically finds the most matched bitmap and scales the bitmap for use.
Therefore, we can infer that the bitmap size generated is different because the Android system automatically scales the image.
Next, let's take a look at how Android Enables automatic scaling of bitmap resources.
Starting with the Java-layer code, we found that in BitmapFactory, decodeResource obtains the Bitmap Code as follows:
final TypedValue value = new TypedValue();is = res.openRawResource(id, value);bm = decodeResourceStream(res, value, is, null, opts);
The code in deoceResourceStream is as follows:
if (opts.inDensity == 0 && value != null) { final int density = value.density; if (density == TypedValue.DENSITY_DEFAULT) { opts.inDensity = DisplayMetrics.DENSITY_DEFAULT; } else if (density != TypedValue.DENSITY_NONE) { opts.inDensity = density; }}if (opts.inTargetDensity == 0 && res != null) { opts.inTargetDensity = res.getDisplayMetrics().densityDpi;}return decodeStream(is, pad, opts);
Here we can also see that Android first obtains the screen pixel density of the most matched drawable object from TypeValue, then, the screen pixels of the drawable object are transmitted to the opts object with the pixel density of the device's own screen, and then the decodeStream method is called for the final bitmap resolution.
Therefore, when Android uses BitmapFactory to parse the image files in drawable, it actually scales according to the image pixel density in the image folder and the pixel density of the existing device.
According to the definition of bitmap, the larger the length and width, the memory usage will also increase in the square level. Therefore, the lower the screen pixel of the drawable folder where the image is placed, the memory usage on the same device increases. (Ps: in actual use, the size of the same image placed in different drawable folders must be different, so there is no major problem .)