**這只是一個android圖片三級緩存的原理,是我從視頻學到的,也是我自己整理一下,應對面試用的。真正用的話建議還是使用xutils.
建議把下面的四個類的代碼看一遍,對理解三級緩存有幫助**
這裏是一個自定義的圖片工具類
public class MyBitmapUtils {
NetCacheUtils mNetCacheUtils;//網絡圖片工具
LocalCacheUtils mLocalCacheUtils;//本地圖片工具類
MemoryCacheUtils memoryCacheUtils;//內存圖片工具類
public MyBitmapUtils() {
memoryCacheUtils = new MemoryCacheUtils();
mLocalCacheUtils = new LocalCacheUtils();
mNetCacheUtils = new NetCacheUtils(mLocalCacheUtils, memoryCacheUtils);
}
//加載圖片的方法
public void display(ImageView ivPic, String url) {
ivPic.setImageResource(R.drawable.news_pic_default);//設置加載默認圖片
Bitmap bitmap=null ;
//先從從內存中讀去圖片
bitmap=memoryCacheUtils.getBitmapFromMemory(url);
if(bitmap!=null){
ivPic.setImageBitmap(bitmap);
return ;
}
//從本地sd卡中讀去圖片
bitmap=mLocalCacheUtils.getBitmapFromLocal(url);
if(bitmap!=null){
//如果讀到了圖片
ivPic.setImageBitmap(bitmap);
memoryCacheUtils.setBitmaptoMemory(url, bitmap);//將圖片保存在內存中
return;
}
//從網絡中讀去圖片
mNetCacheUtils.getBitmapFormNet(ivPic, url);
}
}
接下來是三個讀取圖片工具類
/*從網絡讀取圖片*/
public class NetCacheUtils {
private LocalCacheUtils mlocalCacheUtils;//本地
private MemoryCacheUtils mMemoryCacheUtils;//內存
public NetCacheUtils(LocalCacheUtils localCacheUtils,
MemoryCacheUtils memoryCacheUtils) {
mlocalCacheUtils = localCacheUtils;
mMemoryCacheUtils = memoryCacheUtils;
}
// 從網絡下載圖片
public void getBitmapFormNet(ImageView ivPic, String url) {
new BitmapTask().execute(ivPic, url);//啓動AsyncTask,參數會在doInbackground中獲取 會調用下面的doInBackground(Object... params)等等方法。這可以看作是一個啓動方法
}
class BitmapTask extends AsyncTask<Object, Void, Bitmap> {
private ImageView ivPic;
private String url;
// 後臺耗時方法在此執行,子線程
@Override
protected Bitmap doInBackground(Object... params) {
ivPic = (ImageView) params[0];
url = (String) params[1];
ivPic.setTag(url);// 將url和imageview綁定
return downloadBitmap(url);//自己寫的函數,在下面被調用
}
// 更新進度,主線程
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
// 耗時方法結束後,執行此方法,主線程
//也就是下載圖片結束後
@Override
protected void onPostExecute(Bitmap result) {
if(result!=null){
String bindUrl=(String) ivPic.getTag();
if(url.equals(bindUrl)){//確保圖片設置給了正確的imageview
ivPic.setImageBitmap(result);
mlocalCacheUtils.setBitmapTocal(url, result);//將圖片保存到本地
mMemoryCacheUtils.setBitmaptoMemory(url, result);// 將圖片保存在內存
System.out.println("從網絡緩存讀取圖片了");
}
}
super.onPostExecute(result);
}
}
// 從網絡下載圖片
private Bitmap downloadBitmap(String url) {
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) new URL(url).openConnection();
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
conn.setRequestMethod("GET");
conn.connect();
int responseCode = conn.getResponseCode();
if (responseCode == 200) {
InputStream inputStram = conn.getInputStream();
// 圖片壓縮處理
BitmapFactory.Options option = new BitmapFactory.Options();
option.inSampleSize = 2;// 寬高都壓縮爲原來的二分之一,此參數需要根據圖片要展示的大小來確定
option.inPreferredConfig = Bitmap.Config.RGB_565;// 設置圖片格式
Bitmap bitmap = BitmapFactory.decodeStream(inputStram, null,
option);
return bitmap;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
conn.disconnect();
}
return null;
}
}
本地緩存類
//本地緩存
class LocalCacheUtils {
public static final String CACHE_PATH=Environment.getExternalStorageDirectory().getAbsolutePath()+"/zhbj_cache_52";//圖片存到sd卡中的地址
// 從本地sdcard讀圖片
public Bitmap getBitmapFromLocal(String url) {
try{
//存的時候把圖片的的地址用MD5加密後作爲存儲的名字,所以取得時候也要把地址加密。
String filename=MD5Encoder.encode(url);
File file=new File(CACHE_PATH,filename);
if(file.exists()){
Bitmap bitmap=BitmapFactory.decodeStream(new FileInputStream(file));
return bitmap;
}
}
catch(Exception e){
e.printStackTrace();
}
return null;
}
// 向sdcard寫圖片
public void setBitmapTocal(String url,Bitmap bitmap) {
String filename;
try {
filename = MD5Encoder.encode(url);
File file=new File(CACHE_PATH, filename);
File parentFile=file.getParentFile();
if(!parentFile.exists()){
//如果文件夾不存在,創建文件夾
parentFile.mkdir();
//將圖片保存在本地
bitmap.compress(CompressFormat.JPEG, 100,
new FileOutputStream(file));
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
內存緩存
public class MemoryCacheUtils {
// private HashMap<String , SoftReference<Bitmap>> mMemoryCache=new
// HashMap<String, SoftReference<Bitmap>>();
/*異步加載圖片的例子,網上也比較多,大部分用了HashMap<String, SoftReference<Drawable>> imageCache ,但是現在已經不再推薦使用這種方式了,因爲從 Android 2.3 (API Level 9)開始,垃圾回收器會更傾向於回收持有軟引用或弱引用的對象,這讓軟引用和弱引用變得不再可靠。另外,Android 3.0 (API Level 11)中,圖片的數據會存儲在本地的內存當中,因而無法用一種可預見的方式將其釋放,這就有潛在的風險造成應用程序的內存溢出並崩潰,所以我這裏用得是LruCache來緩存圖片,當存儲Image的大小大於LruCache設定的值,系統自動釋放內存,這個類是3.1版本中提供的,如果你是在更早的Android版本中開發,則需要導入android-support-v4的jar包(這裏要注意咯)*/
private LruCache<String, Bitmap> mMemoryCache;
public MemoryCacheUtils() {
long maxMemory = Runtime.getRuntime().maxMemory() / 8;// 獲取最大內存模擬器默認是16M
mMemoryCache = new LruCache<String, Bitmap>((int) maxMemory) {
@Override
protected int sizeOf(String key, Bitmap value) {
int byteCount = value.getRowBytes() * value.getHeight();// 獲取圖片佔用內存大小
return byteCount;
}
};
}
// 從內存中讀數據
public Bitmap getBitmapFromMemory(String url) {
// 防止內存溢出,但下面的方法實際中不用
// SoftReference<Bitmap> softReference=mMemoryCache.get(url);
// if(softReference!=null){
// Bitmap bitmap=softReference.get();
// return bitmap;
//
//
// }
return mMemoryCache.get(url);
}
// 寫內存
public void setBitmaptoMemory(String url, Bitmap bitmap) {
// SoftReference<Bitmap> softReference = new
// SoftReference<Bitmap>(bitmap);
// mMemoryCache.put(url, softReference);
mMemoryCache.put(url, bitmap);
}
}
調用舉例
private MyBitmapUtils myutils;
myutils.display(holder.ivPic,item.listimage );
//註釋 自己的bitmaoutils
//註釋 holder.ivPic 一個holder中的imgivew.
//註釋 item.listimage 一個圖片的地址
只需知道兩個參數一個是imageivew,一個是url就行
首先會從內存中找圖片,內存中沒有,會在從本地sd卡中讀取,如果從本地找到圖片,會顯示到imgview中,然後順便存到內存中,如果沒有在從網絡中讀取,從網絡中讀到流後,生成bitmap 順便存到內存與sd卡中。
我只是一個菜鳥,視頻裏就是這麼講的,怎麼實際中要用的話,建議用xutils,因爲三級緩存它幫你實現了。