Anroid中圖片的快取策略之LruCache
在安卓的專案開發中必定少不了網路圖片的載入,對與載入少量圖片而言可能問題不大,但是當進行多圖載入的時候如果不進行快取處理的話那麼你的使用者肯定是比較痛苦的,無論是已經看過的圖片或是沒有看過的圖片,都要每次請求網路進行重新獲取。一方面是消耗了使用者的流量,另一方面使用者體驗也不會好到哪去。所以我們在平常的開發中肯定要對這種問題進行處理,以提升使用者體驗,對於這個問題相比聽得最多的就是三級快取了吧(讀起來無比的高大上),其原理就是:當我們第一次開啟應用獲取圖片時,先去網路中去下載圖片然後依次將圖片儲存到記憶體,磁碟中去,當我們下一次再需要這張圖片的時候就不需要重複的到網路上面進行下載,直接可以先去記憶體中找,如果沒有再接著到磁碟中尋找,如果有則直接應用,如果沒有則再去進行網路請求,可以提升應用的效能以及優化前面所提到的糟糕的使用者體驗。這次我們先介紹記憶體中的快取(^__^
下面引出要介紹的類:LruCache(Least Recently Used)
通過縮寫的字面意思可以知道 最近最少使用的,這個類大致實現的演算法就是:當我們訪問了item或者是說需要進行快取的物件(比如說BitMap),這時候這個需要進行快取的物件應該被加入到記憶體當中然後移動到佇列的頂部,如此迴圈之後這個佇列的頂部就應該是最近被訪問的item了,而隊尾就應該是很久沒有訪問過的item,該類中的trimToSize()方法會不斷地檢查當前的快取是否超出了最大的快取,如果超出則移除那條很久沒有訪問過的item。
需要由於是快取在當前app記憶體中的,當我們app退出之後快取就會被移除(所以還要配合磁碟進行快取)
大家如果有興趣的話可以去檢視一下原始碼能夠有一個更清晰的認識。
下面我們通過一個載入妹子圖的栗子,來看一下LruCahce的使用:
使用LruCache快取的效果:
不使用LruCache快取的效果:
看到這裡相信小夥伴們已經看出載入圖片使用快取的優點了吧,對於使用快取來進行圖片的載入,當圖片通過網路請求獲取到了之後,下次就不需要再從網路中進行獲取,而是直接從記憶體中通過key來取出之前存放的BitMap物件(這裡的快取),由於從記憶體中的資料讀取比較快,所以基本上看不到圖片閃爍切換的現象(主要是由ListView的複用產生的,以及網路的非同步耗時的網路請求,會造成圖片閃爍以及錯位的現象)。
下面看一下具體的實現過程:
專案結構:
MyImageView.java(自定義能夠載入網路圖片,並能夠快取BitMap到記憶體中的ImageView):
/**
* Created by wangke on 17-4-2.
*
* 自定義可以載入網路圖片的ImageView,使用LruCache進行將圖片快取到記憶體中去
*/
@SuppressLint("AppCompatCustomView")
public class MyImageView extends ImageView{
private LruCache<String, Bitmap> mCache;
public MyImageView(Context context) {
super(context);
Init();
}
public MyImageView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
Init();
}
public MyImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
Init();
}
private void Init() {
//獲取全域性的LruCache物件
mCache = SingleLruCache.getInstance(getContext());
}
/**
* 載入圖片從網路中
* @param imageUrl
*/
public void loadImageFromUrl(String imageUrl){
//此處的邏輯,從網路上載入下來的圖片,載入成功之後就將其進行快取,下一次再進行獲取圖片的時候,現在本地的
//快取中進行查詢,如果沒有找到的話再進行去網路中請求的操作
new myAsncTask().execute(imageUrl);
}
class myAsncTask extends AsyncTask<String,Void,Bitmap>{
@Override
protected Bitmap doInBackground(String... params) {
String imageUrl = params[0];
Bitmap bitmap = mCache.get(imageUrl);
//在這裡進行判斷,如果快取中存在圖片則直接從裡面取出來,如果沒有再去進行網路的請求
if(bitmap==null){
bitmap = getBitmap(imageUrl);
Log.i("wk","請求網路進行獲取");
}else {
Log.i("wk","從快取中獲取");
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if(bitmap!=null){
setImageBitmap(bitmap);
}
}
}
/**
* 請求網路獲取圖片url的bitmap
* @param imageUrl
* @return
*/
@Nullable
private Bitmap getBitmap(String imageUrl) {
try {
HttpURLConnection conn = (HttpURLConnection) new URL(imageUrl).openConnection();
conn.setRequestMethod("GET");
conn.setReadTimeout(5000);
conn.setConnectTimeout(5000);
conn.setDoInput(true);
int stateCode = conn.getResponseCode();
if(stateCode == 200) {
Log.i("wk", "伺服器返回的狀態碼:" + stateCode);
InputStream inputStream = conn.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
//每一次請求網路獲取的bitmap都儲存在快取中去
if(bitmap!=null && imageUrl!=null) {
mCache.put(imageUrl, bitmap);
Log.i("wk","已快取的大小:"+mCache.size());
}
return bitmap;
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
上面程式碼使用AsyncTask完成網路請求的非同步操作,在進行網路請求前,先判斷快取中是否存在與key相對應的value,如果有就直接取出而不再重新從網路獲取,如果沒有取出資料,則進行從網路載入並將獲取到的Bitmap新增到快取中去。
LruCache類中put(key,value)方法的具體實現:
public final V put(K key, V value) {
if (key == null || value == null) {
throw new NullPointerException("key == null || value == null");
}
V previous;
synchronized (this) {
putCount++;
size += safeSizeOf(key, value);
previous = map.put(key, value); //如果有與key關聯的value則返回value的值,如果沒有則返回空
if (previous != null) {
//執行到此處表明,新增的key在所對應的value在快取中已經存在,所以要撤銷上面增加記憶體的操作,所以 -
size -= safeSizeOf(key, previous);
}
}
if (previous != null) {
entryRemoved(false, key, previous, value); //入口移除
}
trimToSize(maxSize);
return previous;
}
SingleLruCache(單例模式,確保LruCache全域性唯一)
**
* Created by wangke on 17-4-2.
*/
public class SingleLruCache {
private SingleLruCache(){
}
private static LruCache<String,Bitmap> mCache;
public static LruCache getInstance(Context context){
if(mCache == null){
//獲取ActivityManager
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
//獲取Android系統分配給當前app的記憶體大小
int memoryClass = manager.getMemoryClass();
mCache = new LruCache<String, Bitmap>(memoryClass*1024*1024/8){
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
};
}
return mCache;
}
}
上面程式碼中的注意點:
我們在對圖片進行快取的時候,需要建立一個全域性唯一的LruCache用作多個MyImageView物件進行快取處理,這裡用到了單例模式來建立物件確保物件的全域性唯一。
在LruCache的構造方法中設定的最大快取數谷歌推薦應該為系統分配給此應用記憶體大小的八分之一。聽谷歌爸爸的話^_^
sizeOf()方法的預設實現是返回快取的物件的數目,這裡我們要重寫該方法,返回我們所需要的值,這裡我們返回bitmap的位元組數。
後面的ListView 的介面卡的程式碼就不貼了,比較簡單,哈哈最終目標要實現一個可以進行三級快取的圖片載入類O(∩_∩)O哈哈~
清明假期敲敲程式碼,寫寫部落格也還是不錯滴。
相關推薦
Anroid中圖片的快取策略之LruCache
在安卓的專案開發中必定少不了網路圖片的載入,對與載入少量圖片而言可能問題不大,但是當進行多圖載入的時候如果不進行快取處理的話那麼你的使用者肯定是比較痛苦的,無論是已經看過的圖片或是沒有看過的圖片,都要每次請求網路進行重新獲取。一方面是消耗了使用者的流量,另一方面
Android中的快取策略
快取策略的主要流程: 當程式第一次從網路載入圖片後,將其快取到儲存裝置上,下一次就不用再次從網路上獲取了。為了提高應用的使用者體驗,往往還會再記憶體中再快取一份,這樣當應用打算從網路請求一張圖片時,首先從記憶體中讀取,如果沒有那就從儲存裝置中獲取,如果儲存裝置也沒有,那就從網路上下載
iOS快取策略之NSCache的簡單使用
NSCache是一個繼承NSObjec的可變集合,是蘋果提供的一套快取機制,用鍵值(key-value)對來臨時儲存只需要短暫儲存在記憶體中的資料,並且當記憶體空間很少的時候會可以自動釋放一些資源。 概觀 快取(cache)物件和其他可變集合不同的幾個方面。 NSCache類包含了各種自動銷燬
MyBatis快取策略之二級快取
// 建立代理物件 UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class); // 第一次發起請求,查詢id為1的使用者 User user1 = userMapper1.findUserById(1)
Android四大圖片快取框架之-Fresco(一)
本文來自於Fresco中文文件,這僅僅是自己的學習筆記!!!大牛繞路,放我我。 關於Fresco的介紹,請檢視連結 關於android圖片快取,這是一個android程式設計師必須瞭解的。關於四大圖片快取框架的特性與對比,請移步MDCC傳送門 首先說明,本
Android中圖片快取的一些總結
最近在做圖片載入時遇到記憶體溢位問題,所以這裡找到一些資料學習後,在這裡做一個總結。 這裡使用帶了LruCache技術和DiskLruCache技術,簡單地說,LruCache是做的記憶體快取處理,只負責記憶體中圖片的管理,也就是在記憶體中快取被清除後還是需要
Android 開源框架Universal-Image-Loader完全解析(二)--- 圖片快取策略詳解
本篇文章繼續為大家介紹Universal-Image-Loader這個開源的圖片載入框架,介紹的是圖片快取策略方面的,如果大家對這個開源框架的使用還不瞭解,大家可以看看我之前寫的一篇文章Android 開源框架Universal-Image-Loader完全解析(一)---
android中圖片的三級cache策略(記憶體、檔案、網路)之二:記憶體快取策略
前言 記得很久之前我寫了一篇banner的文章,好多朋友找我要程式碼,並要我開放banner中使用的圖片管理工廠-ImageManager。如果想很好地理解下面的故事,請參看我半年前寫的兩篇博文:android中圖片的三級cache策略(記憶體、檔案、網路) 一 和 an
安卓快取之LruCache及設計(非同步+快取)圖片載入器LruCacheImageLoader
一、LruCache LruCache是一套記憶體快取的解決方案,演算法基於LRU。 LRU:Least Recently Used(近期最少使用)。LruCache基於LRU演算法的快取策略。 LruCache是一個泛型類,其以強引用的方式
淺談Android中的非同步載入之ListView中圖片的快取及優化三
隔了很久沒寫部落格,現在必須快速脈動回來。今天我還是接著上一個多執行緒中的非同步載入系列中的最後一個使用非同步載入實現ListView中的圖片快取及其優化。具體來說這次是一個綜合Demo.但是個人覺得裡面還算有點價值的就是裡面的圖片的快取的實現。因為老實說它確實能
Android中圖片的三級緩存策略
getitem 圖片顯示 current sco clas 實例 ase activit fileinput 一、簡單介紹 如今的Android應用程序中。不可避免
易寶典文章——玩轉O365中的EXO服務 之三十三 管理存檔策略
雲計算 Office 365 微軟 郵件歸檔 Exchange 在為用戶啟用了存檔郵箱之後,默認情況下,會將兩年或者兩年以上的郵件從用戶主郵箱移動到就地存檔郵箱,並且將用戶主郵箱中已經刪除並清除到“可恢復的項目”目錄中,早於或等於14天的郵件,移動到就地存檔郵箱的“可恢復的項目”目錄中。如
【Spring Boot】(24)、Spring Boot中使用快取之Spring快取
1、快取依賴 只要新增如下依賴,即可使用快取功能。 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter
Android中圖片優化之WebP使用
一、什麼是 WebP? WebP(發音 weppy,專案主頁),是一種支援有失真壓縮和無失真壓縮的圖片檔案格式,派生自影象編碼格式 VP8。根據 Google 的測試,無失真壓縮後的 WebP 比 PNG 檔案少了 45% 的檔案大小,即使這些 PNG 檔案經過其他壓縮工具壓縮之後,WebP 還
IOS網路圖片快取之SDWebImage
載入網路圖片可以說是網路應用中必備的。如果單純的去下載圖片,而不去做多執行緒、快取等技術去優化,載入圖片時的效果與使用者體驗就會很差。 處理網路圖片快取步驟: 1、根據圖片URL查詢記憶體是否有這張圖片,有則返回圖片,沒有則進入下一步。 2、查詢本地磁碟儲存是否有這張圖片,有則返回圖片,
Android中picasso圖片快取
Picasso是一個圖片快取的庫,可實現圖片的下載和快取,是由Square公司出品, github地址:https://github.com/square/picasso,專案主導者是JakeWharton 大神。 1、Android Studio 配置
Android中使用Universal-Image-Loader圖片快取
ImageLoader 是最早開源的 Android 圖片快取庫, 強大的快取機制, 早期被廣泛 Android 應用使用, 至今仍然有很多 Android 開發者在使用。 GitHub地址:
Android記憶體快取之LruCache
LruCache是什麼? LruCache 是least recentlly used 的簡稱,意思是最近最少使用演算法,它可以實現將最近最少使用的物件回收掉,從而保證記憶體不會超出範圍可將LruCache當成一個容器,它就相當於一個map集合。 為什麼使用Lr
Android快取策略與圖片載入
Android快取策略 Android快取策略 LruCache DiskLruCache glide 鏈式呼叫 配合生命週期使用 快取設定 fresco 新增依賴
android中圖片的三級cache策略(記憶體 檔案 網路) 一
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!