<首先需要下载volley.jar的开发包,并导入项目中: volley.jar>
使用Volley+ImageRequest下载图片,并使用LruCache进行内存缓存,同时使用DiskCache进行硬盘缓存:
首先是ImageCache的接口:
package mxd.com.wxproject.imgList;
import android.graphics.Bitmap;
/**
* Created on 16/6/12.
*/
public interface ImageCache
{
public Bitmap get(String url);
public void put(String url, Bitmap bitmap);
}
MemoryCache用来进行内存缓存:
package mxd.com.wxproject.imgList;
import android.graphics.Bitmap;
import android.util.LruCache;
/**
* Created on 16/6/12.
*/
public class MemoryCache implements ImageCache
{
private static LruCache<String, Bitmap> mCache = null;
private static final String cacheTag = "ImageCache";
public MemoryCache()
{
mCache = initMemoryCache();
}
public LruCache<String, Bitmap> initMemoryCache()
{
if (mCache == null)
{
synchronized (cacheTag)
{
if (mCache == null)
{
int maxMemory = (int) Runtime.getRuntime().maxMemory() / 1024;
int cacheMemory = maxMemory / 4;
mCache = new LruCache<String, Bitmap>(cacheMemory)
{
@Override
protected int sizeOf(String key, Bitmap bitmap)
{
// 每次存储,删除时调用
return bitmap.getRowBytes() * bitmap.getHeight() / 1024;
}
};
}
}
}
return mCache;
}
@Override
public Bitmap get(String url)
{
return mCache.get(url);
}
@Override
public void put(String url, Bitmap bitmap)
{
mCache.put(url, bitmap);
}
}
DiskCache用来进行硬盘缓存:
package mxd.com.wxproject.imgList;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* Created on 16/6/12.
*/
public class DiskCache implements ImageCache
{
private static final String cacheDir = "sdcard/cache/";
@Override
public Bitmap get(String url)
{
return BitmapFactory.decodeFile(cacheDir + url);
}
@Override
public void put(String url, Bitmap bitmap)
{
FileOutputStream fileOutputStream = null;
try
{
fileOutputStream = new FileOutputStream(cacheDir + url);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
} catch (FileNotFoundException e)
{
e.printStackTrace();
}finally
{
if (fileOutputStream != null)
{
try
{
fileOutputStream.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
}
}
}
DoubleCache用来进行双重缓存,每次拿到Bitmap的url时,首先从内存缓存(MemoryCache-LruCache)中获取Bitmap,如果获取得到则setImageBitmap到ImageView,否则则从DiskCache中获取Bitmap,如果获取得到,则setImageBitmap到ImageView上,同时缓存到内存中,否则使用Volley+ImageRequest进行网络下载:
package mxd.com.wxproject.imgList;
import android.graphics.Bitmap;
/**
* Created on 16/6/12
*/
public class DoubleCache implements ImageCache
{
ImageCache memoryCache = null;
ImageCache diskCache = null;
public DoubleCache()
{
memoryCache = new MemoryCache();
diskCache = new DiskCache();
}
@Override
public Bitmap get(String url)
{
Bitmap bmp = memoryCache.get(url);
if (bmp == null)
{
bmp = diskCache.get(url);
if (bmp != null)
{
memoryCache.put(url, bmp);
}
}
return bmp;
}
@Override
public void put(String url, Bitmap bitmap)
{
memoryCache.put(url, bitmap);
diskCache.put(url, bitmap);
}
}
下面是用来执行ImageRequest进行网络请求的RequestQueue的单例:
package mxd.com.wxproject.imgList;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageRequest;
import com.android.volley.toolbox.Volley;
import mxd.com.wxproject.WXApp;
/**
* Created on 16/6/12.
*/
public class HttpQueue
{
public HttpQueue()
{
queues = getHttpQueue();
}
private static final String queueTag = "HttpQueue";
private static RequestQueue queues = null;
private RequestQueue getHttpQueue()
{
if (queues == null)
{
synchronized (queueTag)
{
if (queues == null)
{
queues = Volley.newRequestQueue(WXApp.getAppContext());
}
}
}
return queues;
}
public void addImageRequest(ImageRequest request)
{
queues.add(request);
}
}
下面是用来获取图片的ImageLoaderUtils工具:
package mxd.com.wxproject.imgList;
import android.graphics.Bitmap;
import android.util.LruCache;
import android.widget.ImageView;
import com.android.volley.Response;
import com.android.volley.toolbox.ImageRequest;
import mxd.com.wxproject.WXApp;
/**
* Created on 16/6/8.
*/
public class ImageLoaderUtils
{
private HttpQueue queues = null;
private DoubleCache imageCache = null;
public ImageLoaderUtils()
{
this.imageCache = new DoubleCache();
this.queues = new HttpQueue();
}
public void showImageByVolley(ImageView imageView, String url)
{
if (imageCache.get(url) == null)
{
getBitmapByRequest(imageView, url);
} else
{
imageView.setImageBitmap(this.imageCache.get(url));
}
}
private void getBitmapByRequest(final ImageView imageView, final String url)
{
ImageRequest request = new ImageRequest(url, new Response.Listener<Bitmap>()
{
@Override
public void onResponse(Bitmap bitmap)
{
if (imageView.getTag().equals(url))
{
imageView.setImageBitmap(bitmap);
}
imageCache.put(url, bitmap);
}
}, 0, 0, Bitmap.Config.RGB_565, null);
queues.addImageRequest(request);
}
}
下面是ListView的适配器Adapter:
package mxd.com.wxproject.imgList;
import android.content.Context;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.volley.Response;
import com.android.volley.toolbox.ImageRequest;
import java.util.List;
import mxd.com.wxproject.R;
import mxd.com.wxproject.WXApp;
/**
* Created on 16/6/7.
*/
public class ImgAdapter extends BaseAdapter
{
LayoutInflater inflater;
List<ImgItem> datas;
ImageLoaderUtils loaderUtils;
public ImgAdapter(Context context, List<ImgItem> datas)
{
this.inflater = LayoutInflater.from(context);
this.datas = datas;
loaderUtils = new ImageLoaderUtils();
}
@Override
public int getCount()
{
return datas.size();
}
@Override
public Object getItem(int position)
{
return datas.get(position);
}
@Override
public long getItemId(int position)
{
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder viewHolder = null;
if (convertView == null)
{
convertView = inflater.inflate(R.layout.listview_img, null);
viewHolder = new ViewHolder();
viewHolder.tv_listView_imgName = (TextView) convertView.findViewById(R.id.tv_listView_imgName);
viewHolder.tv_listView_imgNum = (TextView) convertView.findViewById(R.id.tv_listView_imgNum);
viewHolder.img_listView_icon = (ImageView) convertView.findViewById(R.id.img_listView_icon);
convertView.setTag(viewHolder);
} else
{
viewHolder = (ViewHolder) convertView.getTag();
viewHolder.img_listView_icon.setImageBitmap(null);
}
ImgItem item = datas.get(position);
viewHolder.tv_listView_imgName.setText(item.imgName);
viewHolder.tv_listView_imgNum.setText(item.imgNum);
String imgUrl = item.imgUrl;
viewHolder.img_listView_icon.setTag(imgUrl);
loaderUtils.showImageByVolley(viewHolder.img_listView_icon, imgUrl);
return convertView;
}
private class ViewHolder
{
ImageView img_listView_icon;
TextView tv_listView_imgName;
TextView tv_listView_imgNum;
}
}
除上面的代码以外,在HttpQueue.java中,调用Volley的newRequestQueue()方法,对RequestQueue进行实例化时,需要一个Context上下文对象,我们使用Application的上下文对象,保证RequestQueue在整个APP生命周期的有效性:
package mxd.com.wxproject;
import android.app.Application;
import android.content.Context;
/**
* Created on 16/6/7.
*/
public class WXApp extends Application
{
private static Context context;
@Override
public void onCreate()
{
super.onCreate();
context = getApplicationContext();
}
public static Context getAppContext()
{
return context;
}
}
配置AndroidManifest文件,为Application添加name属性:
<application
android:name=".WXApp"
并添加网络权限,SDcard读写权限:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
下面附加ImgItem对象文件(ImgItem.java):
package mxd.com.wxproject.imgList;
/**
* Created on 16/6/7.
*/
public class ImgItem
{
public String imgUrl;
public String imgName = "";
public String imgNum = "-1";
}
有了上面的代码,就可以通过Thread和Runnable实现请求List<ImgItem>的操作,获得成功List<ImgItem>之后,就可以异步显示ListView内容了:
ImgAdapter adapter = new ImgAdapter(getContext(), datas);
listView.setAdapter(adapter);
效果如下: