Android自定義簡單的圖片加載器
廢話不多述,首先來說明下 為什么要用圖片加載器 呢,就是為了避免圖片重復從網絡加載。也就是在第一次從網絡加載之后就把圖片緩存在本地,下次用的時候直接從本地查找,有的話就直接用,沒有再從網絡加載。
加載方式的話又有2種,一種是加載在手機內存中,另一種是緩存到SD卡中。一般Android應用的內存很有限,所以用內存緩存的話當應用重啟時緩存在內存中的就會丟失,但是緩存在內存中比緩存在SD卡中讀取的時候更快,而且緩存在SD卡中需要手動釋放內存,不然就變成了垃圾內存。
接下來分別講下內存緩存和SD卡緩存,先定義一個接口規定2種緩存方式都需要完成的工作,put(加入到緩存當中)和get(從緩存中獲取):
public interface ImageCache {
//用url來唯一標識bitmap
public void put(String url, Bitmap bitmap);
public Bitmap get(String url);
}
緩存到內存的代碼:
public class MemoryCache implements ImageCache{
//用來緩存的工具類對象,通過類聲明可以看出這個類也是通過key-value來存儲對象的
private LruCache<String, Bitmap> mImageCache;
public MemoryCache(){
initImageCache();
}
private void initImageCache() {
//計算當前應用可使用內存
final int maxMemory = (int)(Runtime.getRuntime().maxMemory() / 1024);
//分配作為緩存的內存大小,官方推薦為當前應用可使用內存的1/8
final int cacheSize = maxMemory / 4;
//初始化緩存類
mImageCache = new LruCache<String, Bitmap>(cacheSize){
/*sizeof()方法。這個方法默認返回的是你緩存的item數目,如果你想要自定義size的大小,直接重寫這個方法,返回自定義的值即可*/
@Override
protected int sizeOf(String key, Bitmap bitmap) {
return bitmap.getRowBytes() * bitmap.getHeight() / 1024; } };
}
//將資源加入內存緩存
@Override
public void put(String url, Bitmap bitmap){
mImageCache.put(url, bitmap);
}
//從內存緩存通過url標識來獲取資源
@Override
public Bitmap get(String url){
return mImageCache.get(url);
}
}
緩存到SD卡的代碼如下:
public class DiskCache implements ImageCache {
//緩存路徑
static String cacheDir = "sdcard/cache/";
@Override
public Bitmap get(String url){
return BitmapFactory.decodeFile(cacheDir + url);
}
@Override
void put(String url, Bitmap bmp){
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(cacheDir + url);
bmp.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
} catch (Exception e){
e.printStackTrace();
} finally {
if (fileOutputStream != null){
try {
fileOutputStream.close();
} catch (IOException e){
e.printStackTrace();
}
}
}
}
}
那到底什么時候用什么緩存方式呢?
我們可以在從網絡加載圖片的時候同時緩存在內存和SD卡中,當需要使用圖片資源的時候就先從內存查找,沒有的話再從SD卡中查找,也沒有就從網絡加載再緩存到本地(同時緩存到內存和SD卡)。貼上代碼:
public class DoubleCache implements ImageCache{
MemoryCache mMemoryCache = new MemoryCache();
DiskCache mDiskCache = new DiskCache();
@Override
public Bitmap get(String url){
Bitmap bitmap = mMemoryCache.get(url);
if (bitmap == null){
bitmap = mDiskCache.get(url);
return bitmap;
}
@Override
public void put(String url, Bitmap bmp){
mMemoryCache.put(url, bmp);
mDiskCache.put(url, bmp);
}
}
到這里緩存部分邏輯就寫的差不多了,下面看看具體實現類面代碼:
public class ImageLoader {
//內存緩存
ImageCache mImageCache = new DoubleCache();
//線程池,線程的數量為CPU數,可以同時處理多個緩存線程
//Runtime.getRuntime().availableProcessors() 得到的就是CPU數
ExecutorService mExecutorService = Executors.newFixedThreadPool( Runtime.getRuntime().availableProcessors());
public void displayImage(final String url, final ImageView imageView){
Bitmap bitmap = mImageCache.get(url) ;
if (bitmap != null){
imageView.setImageBitmap(bitmap); return;
}
//圖片還未緩存,開啟線程從網上下載
submitLoadRequest(url, imageView);
}
private void submitLoadRequest(final String imageUrl, final ImageView imageView){
//需要開啟新線程,用url唯一標識
imageView imageView.setTag(imageUrl);
mExecutorService.submit(new Runnable() {
@Override
public void run() {
Bitmap bitmap = downloadImage(imageUrl);
if (bitmap == null){
return;
}
if (imageView.getTag().equals(imageUrl)){
imageView.setImageBitmap(bitmap);
}
mImageCache.put(imageUrl, bitmap);
}});
}
private Bitmap downloadImage(String imageUrl) {
Bitmap bitmap = null;
try {
URL url = new URL(imageUrl);
final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
bitmap = BitmapFactory.decodeStream(conn.getInputStream());
conn.disconnect();
} catch (Exception e){
e.printStackTrace();
}
return bitmap;
}
}
到這里這個簡單的ImageLoader類就寫好了。這就是一個很簡單實用的工具類,網上比較完善的ImageLoader多得是,我寫這篇博客主要是整理一下思路也是分享一下自己的學習成果。當然作為一個學生,我寫的文章肯定存在一些問題或者思考欠缺的地方,也希望大家能指出我的錯誤或不足。
來自:http://www.jianshu.com/p/6b35a813ef48
本文由用戶 sd16d6a5 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!