日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android 使用三级缓存实现对图片的加载

發布時間:2023/12/20 Android 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 使用三级缓存实现对图片的加载 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、概述:

現在android應用中不可避免的要使用圖片,有些圖片是可以變化的,需要每次啟動時從網絡拉取,這種場景在有廣告位的應用以及純圖片應用(比如百度美拍)中比較多。

現在有一個問題:假如每次啟動的時候都從網絡拉取圖片的話,勢必會消耗很多流量。在當前的狀況下,對于非wifi用戶來說,流量還是很貴的,一個很耗流量的應用,其用戶數量級肯定要受到影響。當然,我想,向百度美拍這樣的應用,必然也有其內部的圖片緩存策略。總之,圖片緩存是很重要而且是必須的。

二、實現原理:

實現圖片緩存也不難,需要有相應的cache策略。這里我采用 內存-文件-網絡 三層cache機制,其中內存緩存包括強引用緩存和軟引用緩存(SoftReference),其實網絡不算cache,這里姑且也把它劃到緩存的層次結構中。當根據url向網絡拉取圖片的時候,先從內存中找,如果內存中沒有,再從緩存文件中查找,如果緩存文件中也沒有,再從網絡上通過http請求拉取圖片。在鍵值對(key-value)中,這個圖片緩存的key是圖片url的hash值,value就是bitmap。所以,按照這個邏輯,只要一個url被下載過,其圖片就被緩存起來了。

但這里不使用SoftReference,而使用LruCache進行圖片的緩存
為什么使用LruCache:
這個類非常適合用來緩存圖片,它的主要算法原理是把最近使用的對象用強引用存儲在 LinkedHashMap 中,并且把最近最少使用的對象在緩存值達到預設定值之前從內存中移除。

在過去,我們經常會使用一種非常流行的內存緩存技術的實現,即軟引用或弱引用 (SoftReference or WeakReference)。但是現在已經不再推薦使用這種方式了,因為從 Android 2.3 (API Level 9)開始,垃圾回收器會更傾向于回收持有軟引用或弱引用的對象,這讓軟引用和弱引用變得不再可靠。另外,Android 3.0 (API Level 11)中,圖片的數據會存儲在本地的內存當中,因而無法用一種可預見的方式將其釋放,這就有潛在的風險造成應用程序的內存溢出并崩潰。

三、具體實現:

1)在構造方法里初始化LruCache mCache

if (mCache == null) {// 最大使用的內存空間int maxSize = (int) (Runtime.getRuntime().freeMemory() / 4);mCache = new LruCache<String, Bitmap>(maxSize) {@Overrideprotected int sizeOf(String key, Bitmap value) {return value.getRowBytes() * value.getHeight();}};}

2)去內存中取

Bitmap bitmap = mCache.get(url);if (bitmap != null) {// 直接顯示iv.setImageBitmap(bitmap);return;}

3)去硬盤上取

bitmap = loadBitmapFromLocal(url);if (bitmap != null) {// 直接顯示iv.setImageBitmap(bitmap);return;}

4)從網絡加載

loadBitmapFromNet(iv, url);

四、詳細代碼:

/*** @項目名: 3G緩存加載圖片* @包名: com.android.news.tools* @類名: ImageHelper* @創建者: chen.lin* @創建時間: 2015-4-27 上午10:50:37* */ public class ImageHelper {// 內存緩存池// private Map<String, SoftReference<Bitmap>> mCache = new// LinkedHashMap<String, SoftReference<Bitmap>>();// LRUCahce 池子private static LruCache<String, Bitmap> mCache;private static Handler mHandler;private static ExecutorService mThreadPool;private static Map<ImageView, Future<?>> mTaskTags = new LinkedHashMap<ImageView, Future<?>>();private Context mContext;public ImageHelper(Context context) {this.mContext = context;if (mCache == null) {// 最大使用的內存空間int maxSize = (int) (Runtime.getRuntime().freeMemory() / 4);mCache = new LruCache<String, Bitmap>(maxSize) {@Overrideprotected int sizeOf(String key, Bitmap value) {return value.getRowBytes() * value.getHeight();}};}if (mHandler == null) {mHandler = new Handler();}if (mThreadPool == null) {// 最多同時允許的線程數為3個mThreadPool = Executors.newFixedThreadPool(3);}}public void display(ImageView iv, String url) {// 1.去內存中取Bitmap bitmap = mCache.get(url);if (bitmap != null) {// 直接顯示iv.setImageBitmap(bitmap);return;}// 2.去硬盤上取bitmap = loadBitmapFromLocal(url);if (bitmap != null) {// 直接顯示iv.setImageBitmap(bitmap);return;}// 3. 去網絡獲取圖片loadBitmapFromNet(iv, url);}private void loadBitmapFromNet(ImageView iv, String url) {// 開線程去網絡獲取// 使用線程池管理// new Thread(new ImageLoadTask(iv, url)).start();// 判斷是否有線程在為 imageView加載數據Future<?> futrue = mTaskTags.get(iv);if (futrue != null && !futrue.isCancelled() && !futrue.isDone()) {System.out.println("取消 任務");// 線程正在執行futrue.cancel(true);futrue = null;}// mThreadPool.execute(new ImageLoadTask(iv, url));futrue = mThreadPool.submit(new ImageLoadTask(iv, url));// Future 和 callback/Runable// 返回值,持有正在執行的線程// 保存mTaskTags.put(iv, futrue);System.out.println("標記 任務");}class ImageLoadTask implements Runnable {private String mUrl;private ImageView iv;public ImageLoadTask(ImageView iv, String url) {this.mUrl = url;this.iv = iv;}@Overridepublic void run() {// HttpUrlconnectiontry {// 獲取連接HttpURLConnection conn = (HttpURLConnection) new URL(mUrl).openConnection();conn.setConnectTimeout(30 * 1000);// 設置連接服務器超時時間conn.setReadTimeout(30 * 1000);// 設置讀取響應超時時間// 連接網絡conn.connect();// 獲取響應碼int code = conn.getResponseCode();if (200 == code) {InputStream is = conn.getInputStream();// 將流轉換為bitmapBitmap bitmap = BitmapFactory.decodeStream(is);// 存儲到本地write2Local(mUrl, bitmap);// 存儲到內存mCache.put(mUrl, bitmap);// 圖片顯示:不可取// iv.setImageBitmap(bitmap);mHandler.post(new Runnable() {@Overridepublic void run() {// iv.setImageBitmap(bitmap);display(iv, mUrl);}});}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}/*** 本地種去去圖片* * @param url*/private Bitmap loadBitmapFromLocal(String url) {// 去找文件,將文件轉換為bitmapString name;try {name = MD5Encoder.encode(url);File file = new File(getCacheDir(), name);if (file.exists()) {Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());// 存儲到內存mCache.put(url, bitmap);return bitmap;}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return null;}private void write2Local(String url, Bitmap bitmap) {String name;FileOutputStream fos = null;try {name = MD5Encoder.encode(url);File file = new File(getCacheDir(), name);fos = new FileOutputStream(file);// 將圖像寫到流中bitmap.compress(CompressFormat.JPEG, 100, fos);} catch (Exception e) {e.printStackTrace();} finally {if (fos != null) {try {fos.close();fos = null;} catch (IOException e) {e.printStackTrace();}}}}private String getCacheDir() {String state = Environment.getExternalStorageState();File dir = null;if (Environment.MEDIA_MOUNTED.equals(state)) {// 有sd卡dir = new File(Environment.getExternalStorageDirectory(), "/Android/data/" + mContext.getPackageName()+ "/icon");} else {// 沒有sd卡dir = new File(mContext.getCacheDir(), "/icon");}if (!dir.exists()) {dir.mkdirs();}return dir.getAbsolutePath();} }

五、使用方法:

在Adapter 的getView方法里

ImageView iv = (contentView)findViewById(R.id.iv); String url = "http://localhost:8080/web/1.jpg"; new IamgeHelper(this).display(iv,url);

———————————————————————
有需求者請加qq:136137465,非誠勿擾
(java 架構師全套教程,共760G, 讓你從零到架構師,每月輕松拿3萬)
01.高級架構師四十二個階段高
02.Java高級系統培訓架構課程148課時
03.Java高級互聯網架構師課程
04.Java互聯網架構Netty、Nio、Mina等-視頻教程
05.Java高級架構設計2016整理-視頻教程
06.架構師基礎、高級片
07.Java架構師必修linux運維系列課程
08.Java高級系統培訓架構課程116課時
(送:hadoop系列教程,java設計模式與數據結構, Spring Cloud微服務, SpringBoot入門)
——————————————————————–

總結

以上是生活随笔為你收集整理的Android 使用三级缓存实现对图片的加载的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。