Android 圖片的三級緩存策略,以及大圖片的加載

1.圖片的三級緩存策略

1.內(nèi)存緩存:優(yōu)先加載,速度最快

2.本地緩存:次優(yōu)先級加載,速度次之,

3.網(wǎng)絡(luò)緩存:最后加載,速度由網(wǎng)速決定

2.內(nèi)存緩存

首先創(chuàng)建一個MemoryCacheUtils類,內(nèi)存緩存一般使用LruChche緩存策略,首先需要或者應(yīng)用可用的最大內(nèi)存,然后設(shè)置緩存的可用大小,將圖片的緩存大小設(shè)為最大緩存的1/8或者1/4,應(yīng)在初始化中調(diào)用,因此

public MemoryCacheUtils(){

? ? long maxMemory = Runtime.getRuntime().maxMemory();//獲取最大內(nèi)存,一般默認(rèn)是16MB

? ? //獲取圖片字節(jié)數(shù)

? ? mLruCache = new LruCache((int)maxMemory/8){

? ? ? ? @Override

? ? ? ? protected int sizeOf(String key, Bitmap value) {

? ? ? ? ? ? //獲取圖片字節(jié)數(shù)

? ? ? ? ? ? int byteCount = value.getRowBytes() * value.getWidth();

? ? ? ? ? ? return byteCount;

? ? ? ? }

? ? };

}

內(nèi)存緩存中對圖片的保存和讀取十分簡單

//從內(nèi)存中獲取圖片

public Bitmap getBitmapFormMemory(String url){

? ? return mLruCache.get(url);

}

//將圖片保存在內(nèi)存中

public void saveBitmap2Memory(String url, Bitmap bitmap){

? ? mLruCache.put(url, bitmap);

}

3.本地緩存

本地緩存首先需要獲取SD卡的根目錄的路徑

public static final String CACHE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath()+"/imagememory/";

圖片的保存

首先以Url作為關(guān)鍵字對圖片進(jìn)行保存,在保存時需要對Url進(jìn)行MD5加密,將加密后返回的字符串作為關(guān)鍵字創(chuàng)建文件夾,同時保存圖片

public void saveBitmap2SD(String url, Bitmap bitmap){

? ? //對文件地址進(jìn)行MD5加密

? ? String fileName = null;

? ? try {

? ? ? ? fileName = MD5Encoder.encode(url);

? ? } catch (Exception e) {

? ? ? ? e.printStackTrace();

? ? }

? ? File file = new File(CACHE_PATH, fileName);

? ? File parentFile = file.getParentFile();

? ? if (!parentFile.exists()){

? ? ? ? parentFile.mkdirs();

? ? }

? ? try {

? ? ? ? //將圖片保存到本地

? ? ? ? bitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(file));

? ? } catch (FileNotFoundException e){

? ? ? ? e.printStackTrace();

? ? }

}

圖片的讀取

從SD卡中讀取圖片,首先也需要將傳入的Url進(jìn)行加密并將返回的字符串作為索引,查找對應(yīng)的文件夾中,通過BitmapFactory.decodeStream獲得bitmap

public Bitmap getImageFormSD(String url){

? ? //對文件地址進(jìn)行MD5加密

? ? String fileName = null;

? ? try {

? ? ? ? fileName = MD5Encoder.encode(url);

? ? } catch (Exception e) {

? ? ? ? e.printStackTrace();

? ? }

? ? File file = new File(CACHE_PATH, fileName);

? ? if (file.exists()){

? ? ? ? Bitmap bitmap;

? ? ? ? try {

? ? ? ? ? ? bitmap = BitmapFactory.decodeStream(new FileInputStream(file));

? ? ? ? ? ? return bitmap;

? ? ? ? } catch (FileNotFoundException e){

? ? ? ? ? ? e.printStackTrace();

? ? ? ? }

? ? }

? ? return null;

}

4.網(wǎng)絡(luò)緩存圖片

網(wǎng)絡(luò)緩存圖片時需要將網(wǎng)絡(luò)獲得的圖片緩存到內(nèi)存和SD卡中,因此需要在構(gòu)造方法中初始化內(nèi)存緩存工具類和SD卡緩存工具類

public NetCacheUtils(SDcardCacheUtils sDcardCacheUtils, MemoryCacheUtils memoryCacheUtils){

? ? mSDcardCacheUtils = sDcardCacheUtils;

? ? mMemoryCacheUtils = memoryCacheUtils;

}

從網(wǎng)絡(luò)中獲取圖片是一個耗時操作,因此這里采用AsyncTask異步棧的方式實現(xiàn)圖片的異步下載,因此就需要自定義一個MyAsyncTask繼承與AsyncTask

class MyAsyncTask extends AsyncTask{

? ? @Override

? ? protected Bitmap doInBackground(Object... objects) {

? ? ? ? //拿到傳入的iamge

? ? ? ? mImageView = (ImageView)objects[0];

? ? ? ? mUrl = (String)objects[1];

? ? ? ? mImageView.setTag(mUrl);

? ? ? ? Bitmap bitmap = downloadBitmap(mUrl);

? ? ? ? return bitmap;

? ? }

? ? @Override

? ? protected void onPostExecute(Bitmap bitmap) {

? ? ? ? if (bitmap != null){

? ? ? ? ? ? String url = (String) mImageView.getTag();

? ? ? ? ? ? if (url.equals(mUrl)){

? ? ? ? ? ? ? ? mImageView.setImageBitmap(bitmap);

? ? ? ? ? ? ? ? mMemoryCacheUtils.saveBitmap2Memory(url, bitmap);

? ? ? ? ? ? ? ? mSDcardCacheUtils.saveBitmap2SD(url, bitmap);

? ? ? ? ? ? }

? ? ? ? }

? ? }

}

private Bitmap downloadBitmap(String url) {

? ? HttpURLConnection connection = null;

? ? try {

? ? ? ? connection = (HttpURLConnection) new URL(url).openConnection();

? ? ? ? connection.setReadTimeout(5000);

? ? ? ? connection.setRequestMethod("GET");

? ? ? ? connection.setConnectTimeout(5000);

? ? ? ? connection.connect();

? ? ? ? int code = connection.getResponseCode();

? ? ? ? if (code == 200){

? ? ? ? ? ? InputStream inputStream = connection.getInputStream();

? ? ? ? ? ? Bitmap bitmap = BitmapFactory.decodeStream(inputStream);

? ? ? ? ? ? return bitmap;

? ? ? ? }

? ? } catch (IOException e){

? ? ? ? e.printStackTrace();

? ? } finally {

? ? ? ? connection.disconnect();

? ? }

? ? return null;

}

5.大圖片的加載

1.首先需要拿到位圖的尺寸后,進(jìn)行放縮后再加載位圖

BitmapFactory.Options options = new BitmapFactory.Options();

options.inJustDecodeBounds = true;

BitmapFactory.decodeStream();

int imageWidth = options.outWidth;

int iamgeHight = options.outHeight;

String imageType = options.outMimeType;

2.計算inSampleSize

public static int calculateInSampleZSize(BitmapFactory.Options options, int reqWidth, int reqHeight){

? ? int width = options.outWidth;

? ? int height = options.outHeight;

? ? int inSampleSize = 1;

? ? if (height>reqHeight || width>reqWidth){

? ? ? ? int halfHeight = height / 2;

? ? ? ? int halfWidth = width / 2;

? ? ? ? while ((halfHeight/inSampleSize)>reqHeight && (halfWidth/inSampleSize)>reqWidth){

? ? ? ? ? ? inSampleSize *= 2;

? ? ? ? }

? ? }

? ? return inSampleSize;

}

3.放縮后再加載小位圖

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resid, int reqWidth, int reqHeight){

? ? BitmapFactory.Options options = new BitmapFactory.Options();

? ? options.inJustDecodeBounds = true;

? ? BitmapFactory.decodeResource(res,resid, options);

? ? options.inSampleSize = calculateInSampleZSize(options,reqWidth, reqHeight);

? ? options.inJustDecodeBounds= false;

? ? return BitmapFactory.decodeResource(res,resid,options);

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容