Android图片的三级缓存
圖片的三級緩存目的
主要目的是為了節省流量、加快加載速度;
每個 app 都會有大量的網絡圖片存在,當我們不做處理,每次打開 app 都去加載大量網絡圖片時,會耗費大量的流量,當網速不好時加載速度很慢;
?
三級緩存介紹以及優點
?
三級緩存即:內存緩存、本地緩存和網絡緩存
內存緩存:加載速度快、不耗費流量、優先加載
本地緩存:加載速度快、不耗費流量、次級加載
網絡緩存:加載速度慢、耗費流量、最后加載
?
三級緩存原理
首次打開 app 中的圖片時,通過網絡加載圖片并將圖片保存到本地和內存中。
再次打開 app 時,先從內存緩存中取出圖片;如果沒有,再從本地取出圖片;如果還是沒有說明本地圖片被清理或者圖片為新資源,采用網絡加載圖片。
?
下面是工具類代碼和具體使用的 GitHub?下載地址:https://github.com/wuqingsen/PhotoCache
CSDN 下載地址:https://download.csdn.net/download/wuqingsen1/11082536
?
創建工具類
圖片緩存工具類:BitmapUtils ;
使用方法,第一個參數傳 ImageView 控件;第二個參數傳 String 類型圖片鏈接:
BitmapUtils.getInstance().disPlay(imageView, url); import android.graphics.Bitmap; import android.util.Log; import android.widget.ImageView;import com.example.qd.photocache.R;/*** author: wu* date: on 2019/4/2.* describe:自定義的BitmapUtils,實現三級緩存*/ public class BitmapUtils {private NetCacheUtils mNetCacheUtils;private LocalCacheUtils mLocalCacheUtils;private MemoryCacheUtils mMemoryCacheUtils;private static BitmapUtils bitmapUtils;public static BitmapUtils getInstance() {if (bitmapUtils == null) {bitmapUtils = new BitmapUtils();}return bitmapUtils;}public BitmapUtils() {mMemoryCacheUtils = new MemoryCacheUtils();mLocalCacheUtils = new LocalCacheUtils();mNetCacheUtils = new NetCacheUtils(mLocalCacheUtils, mMemoryCacheUtils);}public void disPlay(ImageView ivPic, String url) {ivPic.setImageResource(R.mipmap.ic_launcher);Bitmap bitmap;//內存緩存bitmap = mMemoryCacheUtils.getBitmapFromMemory(url);if (bitmap != null) {ivPic.setImageBitmap(bitmap);Log.e("=====", "從內存獲取圖片");return;}//本地緩存bitmap = mLocalCacheUtils.getBitmapFromLocal(url);if (bitmap != null) {ivPic.setImageBitmap(bitmap);Log.e("=====", "從本地獲取圖片");//從本地獲取圖片后,保存至內存中mMemoryCacheUtils.setBitmapToMemory(url, bitmap);return;}//網絡緩存mNetCacheUtils.getBitmapFromNet(ivPic, url);} }?
內存緩存工具類:MemoryCacheUtils
/*** author: wu* date: on 2019/4/2.* describe:內存緩存*/ public class MemoryCacheUtils {private LruCache<String,Bitmap> mMemoryCache;public MemoryCacheUtils(){long maxMemory = Runtime.getRuntime().maxMemory()/8; mMemoryCache=new LruCache<String,Bitmap>((int) maxMemory){//用于計算每個條目的大小@Overrideprotected int sizeOf(String key, Bitmap value) {int byteCount = value.getByteCount();return byteCount;}};}/*** 從內存中讀圖片* @param url*/public Bitmap getBitmapFromMemory(String url) { Bitmap bitmap = mMemoryCache.get(url);return bitmap;}/*** 往內存中寫圖片* @param url* @param bitmap*/public void setBitmapToMemory(String url, Bitmap bitmap) { mMemoryCache.put(url,bitmap);} }?
本地緩存工具類?LocalCacheUtils?:
import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Environment;import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream;/*** author: wu* date: on 2019/4/2.* describe:本地緩存*/ public class LocalCacheUtils {private static final String CACHE_PATH= Environment.getExternalStorageDirectory().getAbsolutePath()+"/WerbNews";/*** 從本地讀取圖片* @param url*/public Bitmap getBitmapFromLocal(String url){String fileName = null;//把圖片的url當做文件名,并進行MD5加密try {fileName = MD5Encoder.encode(url);File file=new File(CACHE_PATH,fileName);Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file));return bitmap;} catch (Exception e) {e.printStackTrace();}return null;}/*** 從網絡獲取圖片后,保存至本地緩存* @param url* @param bitmap*/public void setBitmapToLocal(String url,Bitmap bitmap){try {String fileName = MD5Encoder.encode(url);//把圖片的url當做文件名,并進行MD5加密File file=new File(CACHE_PATH,fileName);//通過得到文件的父文件,判斷父文件是否存在File parentFile = file.getParentFile();if (!parentFile.exists()){parentFile.mkdirs();}//把圖片保存至本地bitmap.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(file));} catch (Exception e) {e.printStackTrace();}} }?
網絡緩存工具類 NetCacheUtils?:
import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.widget.ImageView;import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL;/*** author: wu* date: on 2019/4/2.* describe:網絡緩存*/ public class NetCacheUtils {private LocalCacheUtils mLocalCacheUtils;private MemoryCacheUtils mMemoryCacheUtils;public NetCacheUtils(LocalCacheUtils localCacheUtils, MemoryCacheUtils memoryCacheUtils) {mLocalCacheUtils = localCacheUtils;mMemoryCacheUtils = memoryCacheUtils;}/*** 從網絡下載圖片* @param ivPic 顯示圖片的imageview* @param url 下載圖片的網絡地址*/public void getBitmapFromNet(ImageView ivPic, String url) {new BitmapTask().execute(ivPic, url);//啟動AsyncTask}/*** AsyncTask就是對handler和線程池的封裝* 第一個泛型:參數類型* 第二個泛型:更新進度的泛型* 第三個泛型:onPostExecute的返回結果*/class BitmapTask extends AsyncTask<Object, Void, Bitmap> {private ImageView ivPic;private String url;/*** 后臺耗時操作,存在于子線程中* @param params* @return*/@Overrideprotected Bitmap doInBackground(Object[] params) {ivPic = (ImageView) params[0];url = (String) params[1];return downLoadBitmap(url);}/*** 更新進度,在主線程中* @param values*/@Overrideprotected void onProgressUpdate(Void[] values) {super.onProgressUpdate(values);}/*** 耗時方法結束后執行該方法,主線程中* @param result*/@Overrideprotected void onPostExecute(Bitmap result) {if (result != null) {ivPic.setImageBitmap(result);System.out.println("從網絡緩存圖片啦.....");//從網絡獲取圖片后,保存至本地緩存mLocalCacheUtils.setBitmapToLocal(url, result);//保存至內存中mMemoryCacheUtils.setBitmapToMemory(url, result);}}}/*** 網絡下載圖片* @param url* @return*/private Bitmap downLoadBitmap(String url) {HttpURLConnection conn = null;try {conn = (HttpURLConnection) new URL(url).openConnection();conn.setConnectTimeout(5000);conn.setReadTimeout(5000);conn.setRequestMethod("GET");int responseCode = conn.getResponseCode();if (responseCode == 200) {//圖片壓縮BitmapFactory.Options options = new BitmapFactory.Options(); // options.inSampleSize=2;//寬高壓縮為原來的1/2options.inPreferredConfig=Bitmap.Config.ARGB_4444;Bitmap bitmap = BitmapFactory.decodeStream(conn.getInputStream(),null,options);return bitmap;}} catch (IOException e) {e.printStackTrace();} finally {conn.disconnect();}return null;} }?
上面用到了 MD5 加密,MD5 加密工具類:
import java.security.MessageDigest;/*** author: wu* date: on 2019/4/2.* describe:MD5加密*/ public class MD5Encoder {/*** Md5Encoder* @param string*/public static String encode(String string) throws Exception {byte[] hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));StringBuilder hex = new StringBuilder(hash.length * 2);for (byte b : hash) {if ((b & 0xFF) < 0x10) {hex.append("0");}hex.append(Integer.toHexString(b & 0xFF));}return hex.toString();} }?
演示代碼
工具類添加完畢,演示一下三級緩存的具體使用;
新建 adapter ,在里面的每個 item 都去加載圖片;列表長度為10,前五個加載同一張圖片,后五個加載另一張圖片,在 adapter 的 onBindViewHolder 中添加代碼如下:
Log.e("=====position", position + "");if (position > 5) {BitmapUtils.getInstance().disPlay(holder.iv_icon, "http://static.gamemm.com/upload/avatar/201903/29/62018_1553847955.jpg");} else {BitmapUtils.getInstance().disPlay(holder.iv_icon, "http://static.gamemm.com/upload/record/201904/2/62511_1554183931_95789.jpg");}下面是第一次打開 app?打印日志,可以看出:
首次加載沒有打印加載方式,默認是從網絡加載圖片;當圖片加載完成后,因為圖片鏈接一樣,所以直接從內存中取出圖片;
?
下面是關閉進程再次打開 app 的打印日志,可以看出:
進程被銷毀,內存中圖片也就沒有了;所以從本地獲取圖片并存儲到內存中;
?
這是源碼 GitHub?下載地址:https://github.com/wuqingsen/PhotoCache
?
總結
以上是生活随笔為你收集整理的Android图片的三级缓存的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ASP.NET MVC 5 - 给电影表
- 下一篇: halcon边缘检测-autobahn车