图片延迟加载的原理其实非常简单,有两种思路:
第一种思路是后台启动Thread下载图片,下载完成后,通过Message Handle的方式把控制权转让给UI Thread并绘制图片。此方法的优点是比较简单,缺点是不容易封装。
第二种思路是启动异步任务AsyncTask,通过doInBackground()方法获得图片资源之后,再通过onPostExecute()方法在UI Thread中绘制取好的图片。
以上两种方式都可以很好地处理图片的延迟加载。本文通过第一种方式来处理,对图片的延迟加载进行封装,并对性能进行如下优化:
1) 图片加载的线程优先级比UI低一级,这样可以优先处理UI任务。
2) 在内存、磁盘缓存下载的应用程序图片。读取图片的顺序为 内存 -> 磁盘 -> 网络,这样可以避免下载重复的图片,节省网络流量,并且提高响应速度和性能。
3) 本地缓存的图片可能由于某种原因过期,而与服务端不一致,比如服务端更新了图片资源,这个时候本地并不知道,从而导致了图片的不一致性,这也是采取缓存技术提高性能而导致的副作用。为了解决这个问题,可以引入时间戳的概念,当时间戳发生变化之后,重新从网络上获取图片并缓存。
以下将做简要的说明。
首先建立LazyImage对象,此对象包括了图片image,图片的网络资源链接url,以及图片所对应的时间戳(从服务端获得,如果没有时间戳的固定图片,也可以不用设置)。
- package com.whyonly.core.bean;
- import android.graphics.Bitmap;
- public abstract class LazyImage {
- private Bitmap image;
- private String image_url;
- private long timestamp;
- public boolean hasLoadPhoto(){
- return image==null ? false : true;
- }
- public long getTimestamp() {
- return timestamp;
- }
- public void setTimestamp(long timestamp) {
- this.timestamp = timestamp;
- this.hashCode();
- }
- public Bitmap getImage() {
- return image;
- }
- public void setImage(Bitmap image) {
- this.image = image;
- }
- public String getImage_url() {
- return image_url;
- }
- public void setImage_url(String image_url) {
- this.image_url = image_url;
- }
- public String toFileName(){ //convert the url + timestamp to file name to instore to local disk
- String fileName = "";
- if(image_url!=null && image_url.indexOf("/")!=-1 ){
- fileName=image_url.substring(image_url.lastIndexOf("/")+1,image_url.length());
- }
- return fileName+"_"+timestamp;
- }
- }
package com.whyonly.core.bean;
import android.graphics.Bitmap;
public abstract class LazyImage {
private Bitmap image;
private String image_url;
private long timestamp;
public boolean hasLoadPhoto(){
return image==null ? false : true;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
this.hashCode();
}
public Bitmap getImage() {
return image;
}
public void setImage(Bitmap image) {
this.image = image;
}
public String getImage_url() {
return image_url;
}
public void setImage_url(String image_url) {
this.image_url = image_url;
}
public String toFileName(){ //convert the url + timestamp to file name to instore to local disk
String fileName = "";
if(image_url!=null && image_url.indexOf("/")!=-1 ){
fileName=image_url.substring(image_url.lastIndexOf("/")+1,image_url.length());
}
return fileName+"_"+timestamp;
}
}
建立一个下载任务
- //Task for the queue
- private class PhotoToLoad
- {
- public LazyImage lazyImage;
- public ImageView imageView;
- public boolean saveDisk;
- public PhotoToLoad(LazyImage l, ImageView i, boolean s){
- lazyImage=l;
- imageView=i;
- saveDisk = s;
- }
- }
//Task for the queue
private class PhotoToLoad
{
public LazyImage lazyImage;
public ImageView imageView;
public boolean saveDisk;
public PhotoToLoad(LazyImage l, ImageView i, boolean s){
lazyImage=l;
imageView=i;
saveDisk = s;
}
}
以及下载队列
- //stores list of photos to download
- class PhotosQueue
- {
- private Stack<PhotoToLoad> photosToLoadStack=new Stack<PhotoToLoad>();
- //removes all instances of this ImageView
- public void clean(ImageView image)
- {
- for(int j=0 ;j<photosToLoadStack.size();){
- if(photosToLoadStack.get(j).imageView==image)
- photosToLoadStack.remove(j);
- else
- ++j;
- }
- }
- }
//stores list of photos to download
class PhotosQueue
{
private Stack<PhotoToLoad> photosToLoadStack=new Stack<PhotoToLoad>();
//removes all instances of this ImageView
public void clean(ImageView image)
{
for(int j=0 ;j<photosToLoadStack.size();){
if(photosToLoadStack.get(j).imageView==image)
photosToLoadStack.remove(j);
else
++j;
}
}
}
接着建立内存缓冲类:
- class MemoryCache {
- private HashMap<String, SoftReference<Bitmap>> cache=new HashMap<String, SoftReference<Bitmap>>();
- public Bitmap get(String id){
- if(!cache.containsKey(id))
- return null;
- SoftReference<Bitmap> ref=cache.get(id);
- return ref.get();
- }
- public void put(String id, Bitmap bitmap){
- cache.put(id, new SoftReference<Bitmap>(bitmap));
- }
- public void clear() {
- cache.clear();
- }
- }
class MemoryCache {
private HashMap<String, SoftReference<Bitmap>> cache=new HashMap<String, SoftReference<Bitmap>>();
public Bitmap get(String id){
if(!cache.containsKey(id))
return null;
SoftReference<Bitmap> ref=cache.get(id);
return ref.get();
}
public void put(String id, Bitmap bitmap){
cache.put(id, new SoftReference<Bitmap>(bitmap));
}
public void clear() {
cache.clear();
}
}
和本地磁盘缓冲类
- class FileCache {
- private File cacheDir;
- public FileCache(Context context){
- //Find the dir to save cached images
- // if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
- cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"whyonly/cache");
- // else
- // cacheDir=context.getCacheDir();
- Log.d("ImageLoader","cacheDir:"+cacheDir);
- if(!cacheDir.exists())
- cacheDir.mkdirs();
- }
- public File getFile(LazyImage lazyImage){
- String filename= lazyImage.toFileName();
- File f = new File(cacheDir, filename);
- return f;
- }
- public void clear(){
- File[] files=cacheDir.listFiles();
- for(File f:files)
- f.delete();
- }
- }
class FileCache {
private File cacheDir;
public FileCache(Context context){
//Find the dir to save cached images
// if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"whyonly/cache");
// else
// cacheDir=context.getCacheDir();
Log.d("ImageLoader","cacheDir:"+cacheDir);
if(!cacheDir.exists())
cacheDir.mkdirs();
}
public File getFile(LazyImage lazyImage){
String filename= lazyImage.toFileName();
File f = new File(cacheDir, filename);
return f;
}
public void clear(){
File[] files=cacheDir.listFiles();
for(File f:files)
f.delete();
}
}
把图片资源显示到ImageView
- //Used to display bitmap in the UI thread
- class BitmapDisplayer implements Runnable
- {
- Bitmap bitmap;
- ImageView imageView;
- public BitmapDisplayer(Bitmap b, ImageView i){bitmap=b;imageView=i;}
- public void run()
- {
- if(bitmap!=null)
- imageView.setImageBitmap(bitmap);
- else
- imageView.setImageResource(defaultImageResId);
- }
- }
//Used to display bitmap in the UI thread
class BitmapDisplayer implements Runnable
{
Bitmap bitmap;
ImageView imageView;
public BitmapDisplayer(Bitmap b, ImageView i){bitmap=b;imageView=i;}
public void run()
{
if(bitmap!=null)
imageView.setImageBitmap(bitmap);
else
imageView.setImageResource(defaultImageResId);
}
}
最后是通过线程来控制图片的下载和显示过程
- class PhotosLoaderThread extends Thread {
- public void run() {
- try {
- while(true)
- {
- //thread waits until there are any images to load in the queue
- if(photosQueue.photosToLoadStack.size()==0)
- synchronized(photosQueue.photosToLoadStack){
- photosQueue.photosToLoadStack.wait();
- }
- if(photosQueue.photosToLoadStack.size()!=0)
- {
- PhotoToLoad photoToLoad;
- synchronized(photosQueue.photosToLoadStack){
- photoToLoad=photosQueue.photosToLoadStack.pop();
- }
- Bitmap bmp=getBitmap(photoToLoad.lazyImage,photoToLoad.saveDisk);
- memoryCache.put(photoToLoad.lazyImage.toFileName(), bmp);
- String tag=imageViews.get(photoToLoad.imageView);
- if(tag!=null && tag.equals(photoToLoad.lazyImage.toFileName())){
- BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad.imageView);
- Activity a=(Activity)photoToLoad.imageView.getContext();
- a.runOnUiThread(bd);
- }
- }
- if(Thread.interrupted())
- break;
- }
- } catch (InterruptedException e) {
- //allow thread to exit
- }
- }
- }
class PhotosLoaderThread extends Thread {
public void run() {
try {
while(true)
{
//thread waits until there are any images to load in the queue
if(photosQueue.photosToLoadStack.size()==0)
synchronized(photosQueue.photosToLoadStack){
photosQueue.photosToLoadStack.wait();
}
if(photosQueue.photosToLoadStack.size()!=0)
{
PhotoToLoad photoToLoad;
synchronized(photosQueue.photosToLoadStack){
photoToLoad=photosQueue.photosToLoadStack.pop();
}
Bitmap bmp=getBitmap(photoToLoad.lazyImage,photoToLoad.saveDisk);
memoryCache.put(photoToLoad.lazyImage.toFileName(), bmp);
String tag=imageViews.get(photoToLoad.imageView);
if(tag!=null && tag.equals(photoToLoad.lazyImage.toFileName())){
BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad.imageView);
Activity a=(Activity)photoToLoad.imageView.getContext();
a.runOnUiThread(bd);
}
}
if(Thread.interrupted())
break;
}
} catch (InterruptedException e) {
//allow thread to exit
}
}
}
完整的图片加载类如下:
- package com.whyonly.core.wrapper;
- import java.io.File;
- import java.io.InputStream;
- import java.lang.ref.SoftReference;
- import java.net.HttpURLConnection;
- import java.net.URL;
- import java.util.Collections;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.Stack;
- import java.util.WeakHashMap;
- import com.whyonly.core.bean.LazyImage;
- import com.whyonly.core.util.ImageUtil;
- import android.app.Activity;
- import android.content.Context;
- import android.graphics.Bitmap;
- import android.util.Log;
- import android.widget.ImageView;
- public class ImageLoader {
- private static final String TAG = "ImageLoader";
- private MemoryCache memoryCache;
- private FileCache fileCache;
- private Map<ImageView, String> imageViews;
- private PhotosLoaderThread photoLoaderThread;
- private PhotosQueue photosQueue;
- private int defaultImageResId;
- //private Context context;
- public ImageLoader(Context context,int defaultImageResId){
- //Make the background thead low priority. So it will not affect the UI performance
- photoLoaderThread=new PhotosLoaderThread();
- photoLoaderThread.setPriority(Thread.NORM_PRIORITY-1);
- memoryCache=new MemoryCache();
- fileCache=new FileCache(context);
- imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
- photosQueue=new PhotosQueue();
- //this.context = context;
- this.defaultImageResId = defaultImageResId;
- }
- public void displayImage(LazyImage lazyImage, ImageView imageView){
- displayImage(lazyImage,imageView,true);
- }
- public void displayImage(LazyImage lazyImage, ImageView imageView,boolean saveDisk)
- {
- imageViews.put(imageView, lazyImage.toFileName());
- if(lazyImage.getImage()!=null){
- imageView.setImageBitmap(lazyImage.getImage());//get from lazy image
- //Log.d(TAG,"----LazyImage cache:"+lazyImage.toFileName());
- }else{
- Bitmap bitmap=memoryCache.get(lazyImage.toFileName());//get from memory cache
- if(bitmap!=null){
- lazyImage.setImage(bitmap);
- imageView.setImageBitmap(bitmap);
- //Log.d(TAG,"----MEMORY cache:"+lazyImage.toFileName());
- }else
- {
- if(defaultImageResId>0)
- imageView.setImageResource(defaultImageResId);
- else
- imageView.setImageBitmap(null);
- if(lazyImage.getImage_url() != null)
- queuePhoto(lazyImage, imageView,saveDisk);//get from SD card or web
- }
- }
- }
- private void queuePhoto(LazyImage lazyImage, ImageView imageView,boolean saveDisk)
- {
- //This ImageView may be used for other images before. So there may be some old tasks in the queue. We need to discard them.
- photosQueue.clean(imageView);
- PhotoToLoad photosToLoad=new PhotoToLoad(lazyImage, imageView, saveDisk);
- synchronized(photosQueue.photosToLoadStack){
- photosQueue.photosToLoadStack.push(photosToLoad);
- photosQueue.photosToLoadStack.notifyAll();
- }
- //start thread if it's not started yet
- if(photoLoaderThread.getState()==Thread.State.NEW)
- photoLoaderThread.start();
- }
- private Bitmap getBitmap(LazyImage lazyImage,boolean saveDisk)
- {
- if(!saveDisk){
- return ImageUtil.returnBitMap(lazyImage.getImage_url());
- }
- File f=fileCache.getFile(lazyImage);
- //from SD cache
- Bitmap b = ImageUtil.file2Bitmap(f);
- if(b!=null){
- lazyImage.setImage(b);
- //Log.d(TAG,"----FILE cache:"+lazyImage.toFileName());
- return b;
- }
- //from web
- try {
- URL imageUrl = new URL(lazyImage.getImage_url());
- HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
- conn.setConnectTimeout(30000);
- conn.setReadTimeout(30000);
- InputStream is=conn.getInputStream();
- ImageUtil.inputStream2File(is, f);
- lazyImage.setImage(ImageUtil.file2Bitmap(f));
- //Log.d(TAG,"----WEB URL:"+lazyImage.toFileName());
- return lazyImage.getImage();
- } catch (Exception ex){
- //ex.printStackTrace();
- return null;
- }
- }
- //Task for the queue
- private class PhotoToLoad
- {
- public LazyImage lazyImage;
- public ImageView imageView;
- public boolean saveDisk;
- public PhotoToLoad(LazyImage l, ImageView i, boolean s){
- lazyImage=l;
- imageView=i;
- saveDisk = s;
- }
- }
- public void stopThread()
- {
- photoLoaderThread.interrupt();
- }
- //stores list of photos to download
- class PhotosQueue
- {
- private Stack<PhotoToLoad> photosToLoadStack=new Stack<PhotoToLoad>();
- //removes all instances of this ImageView
- public void clean(ImageView image)
- {
- for(int j=0 ;j<photosToLoadStack.size();){
- if(photosToLoadStack.get(j).imageView==image)
- photosToLoadStack.remove(j);
- else
- ++j;
- }
- }
- }
- class PhotosLoaderThread extends Thread {
- public void run() {
- try {
- while(true)
- {
- //thread waits until there are any images to load in the queue
- if(photosQueue.photosToLoadStack.size()==0)
- synchronized(photosQueue.photosToLoadStack){
- photosQueue.photosToLoadStack.wait();
- }
- if(photosQueue.photosToLoadStack.size()!=0)
- {
- PhotoToLoad photoToLoad;
- synchronized(photosQueue.photosToLoadStack){
- photoToLoad=photosQueue.photosToLoadStack.pop();
- }
- Bitmap bmp=getBitmap(photoToLoad.lazyImage,photoToLoad.saveDisk);
- memoryCache.put(photoToLoad.lazyImage.toFileName(), bmp);
- String tag=imageViews.get(photoToLoad.imageView);
- if(tag!=null && tag.equals(photoToLoad.lazyImage.toFileName())){
- BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad.imageView);
- Activity a=(Activity)photoToLoad.imageView.getContext();
- a.runOnUiThread(bd);
- }
- }
- if(Thread.interrupted())
- break;
- }
- } catch (InterruptedException e) {
- //allow thread to exit
- }
- }
- }
- //Used to display bitmap in the UI thread
- class BitmapDisplayer implements Runnable
- {
- Bitmap bitmap;
- ImageView imageView;
- public BitmapDisplayer(Bitmap b, ImageView i){bitmap=b;imageView=i;}
- public void run()
- {
- if(bitmap!=null)
- imageView.setImageBitmap(bitmap);
- else
- imageView.setImageResource(defaultImageResId);
- }
- }
- public void clearCache() {
- memoryCache.clear();
- fileCache.clear();
- }
- public void clearMemoryCache() {
- memoryCache.clear();
- }
- }
- class MemoryCache {
- private HashMap<String, SoftReference<Bitmap>> cache=new HashMap<String, SoftReference<Bitmap>>();
- public Bitmap get(String id){
- if(!cache.containsKey(id))
- return null;
- SoftReference<Bitmap> ref=cache.get(id);
- return ref.get();
- }
- public void put(String id, Bitmap bitmap){
- cache.put(id, new SoftReference<Bitmap>(bitmap));
- }
- public void clear() {
- cache.clear();
- }
- }
- class FileCache {
- private File cacheDir;
- public FileCache(Context context){
- //Find the dir to save cached images
- // if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
- cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"whyonly/cache");
- // else
- // cacheDir=context.getCacheDir();
- Log.d("ImageLoader","cacheDir:"+cacheDir);
- if(!cacheDir.exists())
- cacheDir.mkdirs();
- }
- public File getFile(LazyImage lazyImage){
- String filename= lazyImage.toFileName();
- File f = new File(cacheDir, filename);
- return f;
- }
- public void clear(){
- File[] files=cacheDir.listFiles();
- for(File f:files)
- f.delete();
- }
- }
package com.whyonly.core.wrapper;
import java.io.File;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import java.util.WeakHashMap;
import com.whyonly.core.bean.LazyImage;
import com.whyonly.core.util.ImageUtil;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
import android.widget.ImageView;
public class ImageLoader {
private static final String TAG = "ImageLoader";
private MemoryCache memoryCache;
private FileCache fileCache;
private Map<ImageView, String> imageViews;
private PhotosLoaderThread photoLoaderThread;
private PhotosQueue photosQueue;
private int defaultImageResId;
//private Context context;
public ImageLoader(Context context,int defaultImageResId){
//Make the background thead low priority. So it will not affect the UI performance
photoLoaderThread=new PhotosLoaderThread();
photoLoaderThread.setPriority(Thread.NORM_PRIORITY-1);
memoryCache=new MemoryCache();
fileCache=new FileCache(context);
imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
photosQueue=new PhotosQueue();
//this.context = context;
this.defaultImageResId = defaultImageResId;
}
public void displayImage(LazyImage lazyImage, ImageView imageView){
displayImage(lazyImage,imageView,true);
}
public void displayImage(LazyImage lazyImage, ImageView imageView,boolean saveDisk)
{
imageViews.put(imageView, lazyImage.toFileName());
if(lazyImage.getImage()!=null){
imageView.setImageBitmap(lazyImage.getImage());//get from lazy image
//Log.d(TAG,"----LazyImage cache:"+lazyImage.toFileName());
}else{
Bitmap bitmap=memoryCache.get(lazyImage.toFileName());//get from memory cache
if(bitmap!=null){
lazyImage.setImage(bitmap);
imageView.setImageBitmap(bitmap);
//Log.d(TAG,"----MEMORY cache:"+lazyImage.toFileName());
}else
{
if(defaultImageResId>0)
imageView.setImageResource(defaultImageResId);
else
imageView.setImageBitmap(null);
if(lazyImage.getImage_url() != null)
queuePhoto(lazyImage, imageView,saveDisk);//get from SD card or web
}
}
}
private void queuePhoto(LazyImage lazyImage, ImageView imageView,boolean saveDisk)
{
//This ImageView may be used for other images before. So there may be some old tasks in the queue. We need to discard them.
photosQueue.clean(imageView);
PhotoToLoad photosToLoad=new PhotoToLoad(lazyImage, imageView, saveDisk);
synchronized(photosQueue.photosToLoadStack){
photosQueue.photosToLoadStack.push(photosToLoad);
photosQueue.photosToLoadStack.notifyAll();
}
//start thread if it's not started yet
if(photoLoaderThread.getState()==Thread.State.NEW)
photoLoaderThread.start();
}
private Bitmap getBitmap(LazyImage lazyImage,boolean saveDisk)
{
if(!saveDisk){
return ImageUtil.returnBitMap(lazyImage.getImage_url());
}
File f=fileCache.getFile(lazyImage);
//from SD cache
Bitmap b = ImageUtil.file2Bitmap(f);
if(b!=null){
lazyImage.setImage(b);
//Log.d(TAG,"----FILE cache:"+lazyImage.toFileName());
return b;
}
//from web
try {
URL imageUrl = new URL(lazyImage.getImage_url());
HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
InputStream is=conn.getInputStream();
ImageUtil.inputStream2File(is, f);
lazyImage.setImage(ImageUtil.file2Bitmap(f));
//Log.d(TAG,"----WEB URL:"+lazyImage.toFileName());
return lazyImage.getImage();
} catch (Exception ex){
//ex.printStackTrace();
return null;
}
}
//Task for the queue
private class PhotoToLoad
{
public LazyImage lazyImage;
public ImageView imageView;
public boolean saveDisk;
public PhotoToLoad(LazyImage l, ImageView i, boolean s){
lazyImage=l;
imageView=i;
saveDisk = s;
}
}
public void stopThread()
{
photoLoaderThread.interrupt();
}
//stores list of photos to download
class PhotosQueue
{
private Stack<PhotoToLoad> photosToLoadStack=new Stack<PhotoToLoad>();
//removes all instances of this ImageView
public void clean(ImageView image)
{
for(int j=0 ;j<photosToLoadStack.size();){
if(photosToLoadStack.get(j).imageView==image)
photosToLoadStack.remove(j);
else
++j;
}
}
}
class PhotosLoaderThread extends Thread {
public void run() {
try {
while(true)
{
//thread waits until there are any images to load in the queue
if(photosQueue.photosToLoadStack.size()==0)
synchronized(photosQueue.photosToLoadStack){
photosQueue.photosToLoadStack.wait();
}
if(photosQueue.photosToLoadStack.size()!=0)
{
PhotoToLoad photoToLoad;
synchronized(photosQueue.photosToLoadStack){
photoToLoad=photosQueue.photosToLoadStack.pop();
}
Bitmap bmp=getBitmap(photoToLoad.lazyImage,photoToLoad.saveDisk);
memoryCache.put(photoToLoad.lazyImage.toFileName(), bmp);
String tag=imageViews.get(photoToLoad.imageView);
if(tag!=null && tag.equals(photoToLoad.lazyImage.toFileName())){
BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad.imageView);
Activity a=(Activity)photoToLoad.imageView.getContext();
a.runOnUiThread(bd);
}
}
if(Thread.interrupted())
break;
}
} catch (InterruptedException e) {
//allow thread to exit
}
}
}
//Used to display bitmap in the UI thread
class BitmapDisplayer implements Runnable
{
Bitmap bitmap;
ImageView imageView;
public BitmapDisplayer(Bitmap b, ImageView i){bitmap=b;imageView=i;}
public void run()
{
if(bitmap!=null)
imageView.setImageBitmap(bitmap);
else
imageView.setImageResource(defaultImageResId);
}
}
public void clearCache() {
memoryCache.clear();
fileCache.clear();
}
public void clearMemoryCache() {
memoryCache.clear();
}
}
class MemoryCache {
private HashMap<String, SoftReference<Bitmap>> cache=new HashMap<String, SoftReference<Bitmap>>();
public Bitmap get(String id){
if(!cache.containsKey(id))
return null;
SoftReference<Bitmap> ref=cache.get(id);
return ref.get();
}
public void put(String id, Bitmap bitmap){
cache.put(id, new SoftReference<Bitmap>(bitmap));
}
public void clear() {
cache.clear();
}
}
class FileCache {
private File cacheDir;
public FileCache(Context context){
//Find the dir to save cached images
// if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"whyonly/cache");
// else
// cacheDir=context.getCacheDir();
Log.d("ImageLoader","cacheDir:"+cacheDir);
if(!cacheDir.exists())
cacheDir.mkdirs();
}
public File getFile(LazyImage lazyImage){
String filename= lazyImage.toFileName();
File f = new File(cacheDir, filename);
return f;
}
public void clear(){
File[] files=cacheDir.listFiles();
for(File f:files)
f.delete();
}
}
通过 ImageLoader的包装,应用起来应该非常简单,示例代码如下:
private ImageLoader imageLoader = new ImageLoader(this,R.drawable.nohead);
imageLoader.displayImage(bean, imageView);
以上给出来图片延迟加载的基本概念,以及通过一个示例,说明了如何封装,以便应用程序可以简单地调用。下一篇将通过一个完整的工程例子,对图片的延迟加载,以及ListView的延迟加载加载进行综述。(待续