Android Advanced (12) | understanding of loading and Cache Bitmap

12070003-afc668f1875127c8.png
Contents of this section

A .Bitmap efficient load

Bitmap: Bitmap Android in the middle is a picture, you can be real png format can be jpg and other common image formats.

Efficient loaded core idea: Efficient Load Bitmap mainly use BitmapFactory.Options to load the picture of the desired size. The main principle is that you can press a certain sampling rate to load images after narrowing by BitmapFactory.Options, the picture will be displayed in the ImageView reduced, this will reduce the memory footprint to avoid OOM to a certain extent.

Efficient loading process: as long as the obtained BitmapFactory.Options inSampleSize parameters, i.e. for efficient loading process is as follows:

inSampleSize i.e. the sampling rate, a value of 1 when inSampleSize, showing sampled image size of the original image size; inSampleSize when the value of said sampled image size of the original picture 1/2 of the pixel 1/4 of the original number, and so on. Note that when inSampleSize been given less than 1, it will be treated as a default for processing, and inSampleSize in the official recommendations should be exponential 2.

(1) The parameters inJustDecodeBounds of BitmapFactory.Options set to true and Load picture.
(2) Image taken from BitmapFactory.Options original width and height information, and they correspond to outWidth outHeight parameters.
(3) the sampling rate according to the rules in conjunction with the desired size View target sample rate is calculated.
(4) The inJustDecodeBounds BitmapFactory.Options parameter is set to false, then reload the picture.

The four process implemented in code as follows:

public static Bitmap decodeSampleFromResource(Resource res,int resId,int reqWidth,int reqHeight){
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;  //设置为true
    BitmapFactory.decodeResource(res,resId,options);

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


public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth,int reqHeight){
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if(height > reqHeight || width > reqWidth){
        final int halfHeight = height/2;
        final int halfWidth = width/2;

        while((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth){
            inSampleSize = inSampleSize*2;  //类似于递归
        }
    }

    return inSampleSize;
}


mImageView.setImageBitmap(  //对ImageView使用
    decodeSampledBitmapFromResource(getResources(),R.id.myImage,100,100)
);

Two .Android the caching policy

Cache summary: cache, that is, when the program first loads resources from the Internet, it will be cached on the storage device, so next time you use this picture will not have to get up from the network. Caching policy generally includes adding cache, access and delete these three operations. The most commonly used method is LRU caching algorithm, there are two cache based on the algorithm: LruCache (in the buffer) and DiskLruCache (storage buffer).

1.LruCache

Concept: LRUCache is a generic class, it uses an internal LinkedHashMap stored in the external cache strong reference objects, which provides methods to get and put cache done acquisition and add operations. When the buffer is full, LruCache will first remove the older cached objects, and then added into the new cache. LruCache is thread-safe.

Strong Quote: direct object references.
Soft Quote: When an object is only soft references exist, this object is insufficient system memory will be recycled gc.
Weak References: When an object has only weak references exist, this object will be recycled at any time gc.

public class LruCache<K,V>{  //构造方法
    private final LinkedHashMap<K,V> map;
}

LruCache use:
(1) initialization

int maxMemory = (int)(Runtime.getRuntime().maxMemory()/1024);
int cacheSize = maxMemory/8;
mMemoryCache = new LruCache<String,Bitmap>(cacheSize){
    @Override
    protected int sizeOf(String key,Bitmap bitmap){  //计算缓存对象的大小
        return bitmap.getRowBytes()* bitmap.getHeight()/1024;  //转换单位
    }
};

(2) obtain cache objects

mMemoryCache.get(key)

(3) add a cache object

mMemoryCache.put(key,bitmap)

2.DiskLruCache

DiskLruCache creation: DiskLruCache and can not be created by the construction method, which provides a method for creating open itself:

public static DiskLruCache open(File directory,int appVersion,int valueCount,long maxSize)
/*第一个参数:磁盘缓存在文件系统中的存储路径
第二个参数:应用版本号
第三个参数:单个节点所对应的数据的个数,默认值为1
第四个参数:缓存的总大小,超过这个大小就会自动清除一些缓存*/

DiskLruCache typical creation process is as follows:

private static final long DISK_CACHE_SIZE=1024*1024*50;  //50MB
File diskCacheDir = getDiskCacheDir(mContext,"bitmap");
if(!diskCacheDir.exists()){
    diskCacheDir.mkdirs();
}
mDiskLruCache = DiskLruCache.open(diskCacheDir,1,1,DISK_CACHE_SIZE);

DiskLruCache cache Add: Add the cache to DiskLruCache, the first is the need to get the picture url corresponding key:

private String hashKeyFormUrl(String url){
    String cacheKey;
    try{
        final MessageDigest mDigest = MessageDigest.getInstance("MD5");  //将url中的md5的值作为key
        mDigest.update(url.getBytes());
        cacheKey = bytesToHexString(mDigest.digest());
    }cache(NoSuchAlgorithmException e){
        cacheKey = String.valueOf(url.hashCode());
    }
    return cacheKey;
}



private String bytesToHexString(byte[] bytes){
    StringBuilder sb = new StringBuilder();
    for(int i=0;i<bytes.length;i++){
        String hex = Integer.toHexString(0xFF & bytes[i]);
        if(hex.length() == 1){
            sb.append('0');
        }
        sb.append(hex);
    }
    return sb.toString();
}

After converting to url key, you can obtain Editor object as follows:

String key = hashKeyFormUrl(url);
DiskLruCache.Editor editor = mDiskLruCache.edit(key);
if(editor != null){
    OutputStream outputStream = editor.newOutputStream(DISK_CACHE_INDEX);  //得到一个文件输出流
}

After obtaining the file output stream, we can use this file output stream to write files to the file system among the last to submit only need to write through commit Editor of (), if an abnormality occurs in this process, by Editor the abrot () back the entire operation:

OutputStream outputStream = editor.newOutputStream(DISK_CACHE_INDEX);
if(downloadUrlToStream(url,outputStream)){  //没发生异常,则直接提交
    editor.commit();
}
else{  //发生异常,进行回退
    editor.abrot();
}
mDiskLruCache.flush();

DiskLruCache cache lookup: cache lookup also need to convert the url is key, and then get a Snapshot object via DiskLruCache get methods, can be obtained through the cache object file input stream, then you can get a Bitmap object, according to the file input stream:

Bitmap bitmap = null;
String key = hashKeyFormUrl(url);
DiskLruCache.Snapshot snapShot = mDiskLruCache.get(key);
if(DiskLruCache != null){
    FileInputStream fileInPutStream = (FileInputStream)snapShot.getInputStream(DISK_CACHE_INDEX);
    FileDescriptor fileDescriptor = fileInPutStream.getFD();
    bitmap = mImageResizer.decodeSampledBitmapFromFileDescriptior(fileDescriptor,reqWidth,reqHeight);
    if(bitmap != null){
        addBitmapToMemoryCache(key,bitmap);
    }
}

In the above code, we need to note that after getting the picture (file) input stream, generally does not directly at home the original picture, but the picture to zoom in load by means of BitmapFactory.decodeFileDescriptor.

Reproduced in: https: //www.jianshu.com/p/778260a60e94

Guess you like

Origin blog.csdn.net/weixin_34206899/article/details/91118096