Android's caching mechanism and Bitmap loading

    The caching strategy is very important in Android, especially in image loading;
    
    Currently, the more commonly used caching strategies are LruCache and DiskLruCache; these two are least recently used algorithms. The core idea of ​​this algorithm is: when the cache is full, go back and eliminate the least recently used cache objects. Let's talk about the usage of these two caching strategies.
    LruCache:
  LruCache is often used as a memory cache. It is a generic class. Internally, a LinkedHashMap is used to store external cache objects in a strong reference manner. The implementation of LruCache is to directly new LruCache objects, which need to provide the cache capacity and rewrite the sizeOf method.
 
 
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
int cacheSize = maxMemory / 8;
mMemoryCache = new LruCache<String, Bitmap>(cacheSize){
    @Override
protected int sizeOf    (String key, Bitmap value) {
        return value.getRowBytes() * value.getHeight() / 1024;
    }
};


    DiskLruCache:
    DiskLruCache is often used as a storage device cache, that is, a disk cache, which achieves the effect of caching by writing cache objects to the file system. It cannot be used directly, you need to download the source code from the Internet.
       The creation of DiskLruCache cannot be created through the construction method, but it provides the open method for creation. The following creation code is implemented:
 
  
// Get the cache path, generally in the /sdcard/Android/data/package_name/cache directory File diskCacheDir = getDiskCacheDir( mContext , "bitmap" ) ; if (!diskCacheDir.exists()) { // If it does not exist, then Create a directory diskCacheDir.mkdirs() ; } // Determine whether the available disk space is enough, create a DiskLruCache object if (getUsableSpace(diskCacheDir) > CACHE_SIZE ) { try { mDiskLruCache = DiskLruCache.open ( diskCacheDir , 1 , 1 ,DISK_CACHE_SIZE ) ; } catch (IOException e) { e.printStackTrace() ; }}

After talking about the two commonly used caching strategies in Android, let's talk about the loading of Bitmap.
    In Android, loading a Bitmap is achieved through the BitmapFactory class. The BitmapFactory class provides 4 methods: decodeFile, decodeResource, decodeStream and decodeByteArray, which are used to support loading a Bitmap from files, resources, input streams and byte arrays respectively. .
    So in Android, how can we efficiently load Bitmap?
    It is mainly implemented through BitmapFactory.Options, mainly using its inSampleSize parameter, that is, the sampling rate. When the value of inSampleSize is 1, the size of the sampled image is the same as the size of the original image; when the value is 2, the size of the sampled image is 1/2 * 1/2 = 1/4 of the original image size; so the key is To calculate the value of inSmapleSize according to the corresponding algorithm;
    The worthwhile process to get inSampleSize:
    
public Bitmap decodeSampledBitmapFromResource (Resources res , int resId , int reqWidth , int reqHeigth) {
     final BitmapFactory.Options options = new BitmapFactory.Options() ;
 // When inJustDecodeBounds = true , BitmapFactory will only load the original width and height of the image,
 // Does n't really load the image

             options. inJustDecodeBounds = true;
     BitmapFactory. decodeResource (res , resId , options) ;
 // Calculate inSampleSize

        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeigth);
    
    options.inJustDecodeBounds = false;
    return 
BitmapFactory.decodeResource(res, resId, options);
}

private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeigth) {
    int inSampleSize = 1;    if (reqHeigth == 0 || reqWidth == 0) {
        return inSampleSize;
}

    

    final int width = options.outWidth;
    final int heigth = options.outHeight;
    if 
(width > reqWidth || heigth > reqHeigth) {
        final int halfWidth = width/2;
        final int halfHeigth = heigth/2;
        while ((halfWidth / inSampleSize) > reqWidth && (halfHeigth / inSampleSize) > reqHeigth) {
            inSampleSize *= 2;
        }
    }    return inSampleSize;
}

In this way, the value of the sampling rate can be obtained.

Next, let's talk about how to optimize Listview.

1. First, do not perform time-consuming operations in the getView of the Adapter, and use an asynchronous method to load the image; then, it is the Item reuse of the ListView;
2. When the ListView scrolls up and down, stop loading the picture; wait until the scrolling stops, and then load the picture. You can set setOnScrollListener for ListView, and judge whether the list is in a sliding state in the onScrollStateChanged method of OnScrollListener;
3. You can enable hardware acceleration: by setting android:hardwareAccelerated="true";


Record the problems encountered in the process of learning the Android cache mechanism:

1. imageView.setTag(tag, uri) prompts that tag must be resource ID
    Solution: Create an item in the strings.xml file, the name is TAG, and then define a tag = R.id.TAG, so that no error will be reported.
2. After adding item to the strings.xml file, and clicking AS to run, an error will be reported, indicating that the resource id is inconsistent in the two folders
    Solution: Click build on the menu, select Rebuild Project to recompile, and then run it again.

 Remarks: This article is mainly a personal learning record of artistic exploration through Android development. If there is something wrong, please correct it. thank you very much! 
 


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324821940&siteId=291194637