1. Efficient loading of Bitmap
BitMapFactory provides four types of methods: decodeFile, decodeResource, decodeStream and decodeByteArray are used to load a Bitmap object from the file system, resources, input streams and byte arrays respectively.
Efficient loading of Bitmap is very simple, that is, adoptTo load the required size picture.
You can load the reduced image at a certain sampling rate and place the reduced image in ImageView to display.
The sampling rate can be efficiently loaded, and the sampling rate can be obtained in the following ways:
- Will
- from
- Calculate the sampling rate based on the sampling rate rules and combined with the required size of the target View
- Will
After the above four steps, the loaded picture is the final zoomed picture, and of course it is possible that there is no zoom.
The code implementation is as follows:
public Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { // First decode with inJustDecodeBounds=true to check dimensions final options = new (); = true; (res, resId, options); // Calculate inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set = false; return (res, resId, options); } public int calculateInSampleSize( options, int reqWidth, int reqHeight) { if (reqWidth == 0 || reqHeight == 0) { return 1; } // Raw height and width of image final int height = ; final int width = ; (TAG, "origin, w= " + width + " h=" + height); int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; // Calculate the largest inSampleSize value that is a power of 2 and // keeps both height and width larger than the requested height and width. while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) { inSampleSize *= 2; } } (TAG, "sampleSize:" + inSampleSize); return inSampleSize; }
In actual use, you can use it like the following. For example, if you load an image size of 100*100, you can load the image efficiently like the following:
( decodeSampledBitmapFromResource(getResource(),,100,100));
2. Cache Policy in Android
The commonly used algorithm at present is LRU, which means the algorithm used in the nearest time. When the cache is full, the cache objects that are least used in the nearest time will be eliminated first.
2.1 LruCache
LruCache is a generic class, and its internal implementation mechanism is that LinkedHashMap stores external cache objects in a strong reference manner, providingget()
and put()
to complete the access of cache objects. When the cache is full, remove the earlier cache object and add new ones. LruCache is thread-safe.
- Strong quotation: Direct object quotation
- Soft reference: When an object only has soft references and the system memory is insufficient, it will be recycled by gc
- Weak reference: When an object has only weak references, it will be recycled at any time
2.2 DiskLriCache
DiskLruCache is used to implement storage device caching, that is, disk cache.
2.2.1 Creation of DiskLruCache
Since it is not part of the Android SDK, it cannot be created through constructors, providingopen()
Methods are used for their own creation
public static DiskLruCache open(File directory,int appversion,int valueCount,long maxSize);
A typical DiskLruCache creation process
private static final Disk_CACHE_SIZE = 1024*1024*50;//50M File diskCaCheDir = getDiskCacheDir(mContext,"bitmap"); if(!()){ (); } mDiskLruCache = (diskCaCheDir,1,1,Disk_CACHE_SIZE);
The third parameter represents the data corresponding to a single node, and is generally set to 1.
2.2.2 DiskLruCache Cache Adding The cache is done through Editor, which represents an editing object of a cache object. DiskLruCache does not allow editing of a cache object at the same time.
2.2.3 Cache lookup for DiskLruCache
The cache search process also needs to convert the url to a key, through DiskLruCacheget()
Get a Snapshot object, and then through this object, you can get the cached file input stream, and you can get the Bitmap object. In order to avoid OOM during loading, the original image will not be loaded directly. Introduced earlier
To load a scaled picture, but that method has a problem with the scaling of FileInputStream because FileInputStream is an ordered file stream, and the two decodeStream calls affect the location properties of the file stream, resulting in the second decodeStream getting null. To solve this problem, the corresponding file descriptor can be obtained through the file stream, and then through
Method to load a zoomed image.
Bitmap bitmap = null; String key = hashKeyFormUrl(url); snapShot = (key); if (snapShot != null) { FileInputStream fileInputStream = (FileInputStream)(DISK_CACHE_INDEX); // Get the file descriptor FileDescriptor fileDescriptor = (); // Load a zoomed image by bitmap = (fileDescriptor, reqWidth, reqHeight); if (bitmap != null) { addBitmapToMemoryCache(key, bitmap); } } return bitmap; }
Implementation of ImageLoader
It has functions such as synchronous loading of pictures, asynchronous loading, image compression, memory cache, disk cache and network pulling.
3.1 Picture compression function
As mentioned earlier.
3.2 Implementation of memory cache and disk cache
Select LruCache and DiskLruCache to complete the memory cache and disk cache respectively
3.3 Interface design for synchronous loading and asynchronous loading
About synchronous loading: From the implementation of loadBitmap, it can be seen that the working process follows the following steps: first try to read the picture from the memory cache, then read the picture from the disk cache, and finally try to pull the picture from the network. In addition, this method cannot be called in the main thread, otherwise an exception will be thrown. Because loading images is a time-consuming operation.
About asynchronous loading: From bindBitmap, it can be seen that binfBitmap will first try to read the result from the memory cache, and if it succeeds, it will be returned directly, otherwise it will be called from the thread pool.loadBitmap()
, After the loading is successful, let’s talk about the image, the image address and the ImageView that needs to be bound to be encapsulated into a loaderResult object, and send a message to the main thread through mMainHandler, so that you can set pictures for the ImageView in the main thread. Asynchronous loading of images is a very useful function. Many times the caller does not want to load images in a synchronous manner in a separate thread, and sets the image to the required ImageVIew, so the ImageLoader needs to load images in the internal thread and sets the image to the required ImageView.
ImageLoader source code can be clicked here:downloadCheck out the implementation of ImageLoader
IV. Use of ImageLoader
The core is ImageAdapter, whichgetView()
The core method is as follows:
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { convertView = (.image_list_item,parent, false); holder = new ViewHolder(); = (ImageView) (); (holder); } else { holder = (ViewHolder) (); } ImageView imageView = ; final String tag = (String)(); final String uri = getItem(position); if (!(tag)) { (mDefaultBitmapDrawable); } if (mIsGridViewIdle && mCanGetBitmapFromNetWork) { (uri); // This sentence handed over the complex loading process of the image to ImageLoader (uri, imageView, mImageWidth, mImageWidth); } return convertView; }
For the above code ImageAdapter, the complex process of loading images of ImageLoader does not need to be known.
Optimization list stuttering phenomenon:
- Don't load images in getView(), it will definitely take time. As in this example, leave it to ImageLoaer to implement it.
- Control the asynchronous loading frequency. If the user deliberately slides up and down frequently, hundreds of asynchronous tasks may be loaded in an instant, which will cause congestion to the thread pool. The solution is to consider stop loading the image when the user slides the list. When the list stops, the asynchronous loading task is being performed.
- Turn on hardware acceleration: add configuration to Activity android:hardwareAccelerated="true"
Summarize
The above is the entire content of this article. I hope the content of this article will be of some help to me android developers. If you have any questions, you can leave a message to communicate.