涉及的技术: Volley & DiskLruCache & LruCache
效果图(主要是因为缓存在内存里面, 所以滑动的时候比较顺畅. 而且网络图片会缓存到磁盘, 所以相册可以离线使用)
NetHelper.java(单例获取Volley的RequestQueue)
public class NetHelper {
private volatile static NetHelper netHelper;
private RequestQueue requestQueue;
static public NetHelper getInstance(Context context) {
if (netHelper==null){
synchronized (NetHelper.class){
if (netHelper==null){
netHelper=new NetHelper(context.getApplicationContext());
}
}
}
return netHelper;
}
public NetHelper(Context context){
requestQueue=Volley.newRequestQueue(context);
}
public RequestQueue getRequestQueue(){
return requestQueue;
}
}
MainActivity.java
public class MainActivity extends Activity {
private int screenWidth;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_imageloader_main);
WindowManager wm = this.getWindowManager();
screenWidth = wm.getDefaultDisplay().getWidth();
GridView gridView= (GridView) findViewById(R.id.gridview);
gridView.setAdapter(new MyAdapter(getApplicationContext()));
}
class MyAdapter extends BaseAdapter{
private final Context context;
LayoutInflater lf;
public MyAdapter(Context context){
this.context=context;
lf=LayoutInflater.from(context);
}
@Override
public int getCount() {
return imageThumbUrls.length;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView=null;
if (convertView==null){
convertView=lf.inflate(R.layout.item_gridview,parent,false);
imageView= (ImageView) convertView.findViewById(R.id.imageview);
ViewGroup.LayoutParams layoutParams=imageView.getLayoutParams();
layoutParams.width=layoutParams.height=screenWidth/3;
imageView.setLayoutParams(layoutParams);
}
if (imageView==null) imageView= (ImageView) convertView.findViewById(R.id.imageview);
ImageHelper.setImageViewByUrl(context,imageView,imageThumbUrls[position]);
return convertView;
}
}
public final static String[] imageThumbUrls = new String[] {
"https://img-my.csdn.net/uploads/201407/26/1406383299_1976.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383291_6518.jpg",
...(省略n个图片地址)
"https://img-my.csdn.net/uploads/201407/26/1406383290_1042.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383275_3977.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383265_8550.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383264_3954.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383264_4787.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383264_8243.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383248_3693.jpg",
"https://img-my.csdn.net/uploads/201407/26/1406383243_5120.jpg"
};
}
ImageHelper.java
public class ImageHelper {
private volatile static ImageHelper imageHelper;
private final int screenWidth;
ImageLoader imageLoader;
private ImageHelper(final Context context) throws IOException {
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
screenWidth = wm.getDefaultDisplay().getWidth();
//
final File cacheFile=new File(getDiskCacheDir(context)+File.separator);
if (!cacheFile.exists()) cacheFile.mkdirs();
ImageLoader.ImageCache imageCache= new ImageLoader.ImageCache() {
DiskLruCache diskLruCache=DiskLruCache.open(cacheFile,1,1,32*1024*1024);
LruCache<String,Bitmap> lruCache=new LruCache<String,Bitmap>((int)(Runtime.getRuntime().maxMemory()/8)){
@Override
protected int sizeOf(String key, Bitmap bm) {
return bm.getByteCount();
}
};
//getBitmap返回null才调用putBitmap
@Override
public Bitmap getBitmap(String key) {
key=fixKey(key);
//get cache from memory
Bitmap bm=lruCache.get(key);
//get cache from disk
FileInputStream fileInputStream=null;
if (bm==null){
// Log.e("getBitmap","disk cache: "+key);
try {
DiskLruCache.Snapshot snapshot=diskLruCache.get(key);
if (snapshot != null) {
fileInputStream=(FileInputStream) snapshot.getInputStream(0);
bm= BitmapFactory.decodeFileDescriptor(fileInputStream.getFD());
Log.e("getBitmap",bm.getWidth()+" "+bm.getHeight()+" "+bm.getByteCount());
//write to memory cache
lruCache.put(key, bm);
}else{
//没有磁盘缓存
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileInputStream!=null){
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}else{
// Log.e("getBitmap","mem cache");
}
return bm;
}
@Override
public void putBitmap(String key, Bitmap bitmap) {
key=fixKey(key);
//scale bitmap
//volley 有些图片基本没怎么压缩, 所以要手动干这事情
Matrix matrix = new Matrix();
matrix.postScale(screenWidth/3.0f/bitmap.getWidth(),screenWidth/3.0f/bitmap.getHeight()); //长和宽放大缩小的比例
Bitmap resizeBmp = Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);
//write memory cache
lruCache.put(key, resizeBmp);
Log.e("putBitmap", "men cache");
//write disk cache
OutputStream out=null;
try {
if (diskLruCache.get(key)!=null) return;
Log.e("putBitmap","disk cache");
DiskLruCache.Editor editor=diskLruCache.edit(key);
out=editor.newOutputStream(0);
resizeBmp.compress(Bitmap.CompressFormat.PNG, 50,out );
out.flush();
editor.commit();
out.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out!=null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
};
imageLoader=new ImageLoader(NetHelper.getInstance(context).getRequestQueue(),imageCache);
}
public static String getDiskCacheDir(Context context) {
String cachePath=null;
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
|| !Environment.isExternalStorageRemovable()) {
cachePath = context.getExternalCacheDir().getPath();
} else {
cachePath = context.getCacheDir().getPath();
}
return cachePath;
}
static public ImageHelper getInstance(final Context context) {
if (imageHelper==null){
synchronized (ImageHelper.class){
if (imageHelper==null){
try {
imageHelper=new ImageHelper(context.getApplicationContext());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return imageHelper;
}
public static void setImageViewByUrl(Context context, ImageView imageView, String url) {
long beg=System.currentTimeMillis();
getInstance(context).imageLoader.get(url,
ImageLoader.getImageListener(imageView, R.mipmap.ic_launcher, R.mipmap.ic_launcher));
// Log.e("time", System.currentTimeMillis() - beg + "");
}
public static String fixKey(String key) {
char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
try {
byte[] btInput = key.getBytes();
// 获得MD5摘要算法的 MessageDigest 对象
MessageDigest mdInst = MessageDigest.getInstance("MD5");
// 使用指定的字节更新摘要
mdInst.update(btInput);
// 获得密文
byte[] md = mdInst.digest();
// 把密文转换成十六进制的字符串形式
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
String res=new String(str);
return res;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
主要思路是, 先检查内存有没有图片的缓存, 如果没有再检查磁盘的缓存, 还是没有就用Volley获取图片