对图片image进行双缓存

对网络图片下载,并显示在相对应的控件上,为了避免重复连网下载,可以对相应的图片进行双缓存设计,节省时间和流量

设计罗辑

当app启动后,如果控件需要显示网络图片,首先从自己的内存缓存读取,如果没有,再从自己的磁盘缓存读取,再没有,直接上网下载(下载时按照要显示的比例下载保存图片,不用下原图),下载好图片后,保存到内存缓存和磁盘缓存中,当下次需再重新加载图片时,又重新按照加载顺序一一读取,如果读取到直接显示图片即可

内存缓存在app关闭时会自动释放,磁盘缓存则在app册除时会自动删除,而且当app的版本更新时,碰盘缓存会自动删掉原来的图片,而更新最新版的图片


主Activity

package com.example.xin_utils_downwebimage2cachedemo;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.net.ssl.HttpsURLConnection;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import com.jakewharton.disklrucache.DiskLruCache;

import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.support.v4.util.LruCache;
import android.view.Display;
import android.view.Menu;
import android.view.View;
import android.widget.ImageView;

/**
 * 手动双缓存图片,1存放内存缓存,2存放磁盘缓存 在加载图片时,先从内存缓存取,如果没有,再从磁盘缓存取,再没有,从网络下载
 * 下载后马上存进内存缓存和磁盘缓存 以上功能,在ImageLoder第三方框架可以轻松实现,在这里只是为了熟悉相同的原理而自己制作
 * 
 * @author Administrator
 * 
 */
public class MainActivity extends Activity {

	private static final String IMAGEPATH = "http://pic2.52pk.com/files/120203/309295_150703_3923.jpg";
	private static final String KEY = "B1";

	ImageView iv;
	Bitmap bitmap;
	LruCache lru;
	DiskLruCache diskLryCache;
	MyHandler myHandler;
	String md5Key;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		myHandler = new MyHandler();
		iv = (ImageView) findViewById(R.id.imageView1);
		init();
	}

	private void init() {
		// 获取到当前activity可用内存的最大值,使用内存超出这个值会引起OutOfMemory异常。
		// LruCache通过构造函数传入缓存值,以KB为单位。
		int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
		// 使用最大可用内存值的1/8作为缓存的大小。
		int cacheSize = maxMemory / 8;
		System.out.println("cacheSize=" + cacheSize);
		lru = new LruCache<String, Bitmap>(cacheSize);
		File cacheDir = getDiskCacheDir(this, "bitmap");
		if (!cacheDir.exists()) {
			cacheDir.mkdirs();
		}
		try {
			diskLryCache = DiskLruCache.open(cacheDir, getAppVersion(this), 1,
					10 * 1024 * 1024);
		} catch (IOException e) {
			e.printStackTrace();
		}
		md5Key = encrypByMd5(IMAGEPATH);
	}

	// 获取SD卡的磁盘缓存地址
	public File getDiskCacheDir(Context context, String uniqueName) {
		String cachePath;
		// 当SD卡存在或者SD卡不可被移除的时候
		if (Environment.MEDIA_MOUNTED.equals(Environment
				.getExternalStorageState())
				|| !Environment.isExternalStorageRemovable()) {
			cachePath = context.getExternalCacheDir().getPath();
		} else {
			cachePath = context.getCacheDir().getPath();
		}
		System.out.println("碰盘缓存地址=" + cachePath + File.separator + uniqueName);
		return new File(cachePath + File.separator + uniqueName);
	}

	// 获取当前app的版本号
	public int getAppVersion(Context context) {
		try {
			PackageInfo info = context.getPackageManager().getPackageInfo(
					context.getPackageName(), 0);
			return info.versionCode;
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		return 1;
	}

	public void addLocalImage(View view) {
		System.out.println("加载本地图片lc");
		myHandler.obtainMessage(0).sendToTarget();
	}

	public void clickDown(View view) {
		System.out.println("onclick");
		downWebImage(IMAGEPATH);

	}

	// 使用异步加载网络图片,也可以用new Thread().start()
	private void downWebImage(final String url) {
		// 参数:1= 传进来的参数url类形,2=下载网络图片时的%比,3=下载的文件类形
		new AsyncTask<String, Integer, Bitmap>() {
			@Override
			protected Bitmap doInBackground(String... params) {
				try {
					if (lru.get(KEY) == null) {
						System.out.println("虚拟内存无文件");
						DiskLruCache.Snapshot snapShot = diskLryCache
								.get(md5Key);
						if (snapShot != null) {
							System.out.println("磁盘内存有文件");
							InputStream is = snapShot.getInputStream(0);
							bitmap = BitmapFactory.decodeStream(is);

						} else {
							System.out.println("磁盘内存无文件");

							URL urlS = new URL(params[0]);
							HttpURLConnection conn = (HttpURLConnection) urlS
									.openConnection();
							conn.connect();
							InputStream is = conn.getInputStream();
							byte[] bytes = toByteArray(is);
							Options opts = new Options();
							// 根据计算出的比例进行缩放(根据不同的手机屏幕大小,获取最适合的图片大小,
							// 可以节省内存空间,不用每次都把原图下载),也可以指定下载大小
							int scale = getScare(params[0],bytes,opts);
							opts.inSampleSize = scale;
							opts.inJustDecodeBounds = false;
							bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts);
							System.out.println("lru=空,创建");
							try {
								DiskLruCache.Editor editor = diskLryCache
										.edit(md5Key);
								if (editor != null) {
									OutputStream outputStream = editor
											.newOutputStream(0);
									if (bitmap.compress(
											Bitmap.CompressFormat.JPEG, 100,
											outputStream)) {
										editor.commit();
									} else {
										editor.abort();
									}
								}

								diskLryCache.flush();
							} catch (IOException e) {
								e.printStackTrace();
							}
							// is.close();
							// conn.disconnect();

						}
						// if (!filePath.exists()) {
						// System.out.println("SD卡无文件");
						// URL urlS = new URL(params[0]);
						// HttpURLConnection conn = (HttpURLConnection)
						// urlS.openConnection();
						// conn.connect();
						// InputStream is = conn.getInputStream();
						// Options opts = new Options();
						// // 根据计算出的比例进行缩放(根据不同的手机屏幕大小,获取最适合的图片大小,
						// //可以节省内存空间,不用每次都把原图下载),也可以指定下载大小
						// int scale = getScare(params[0]);
						// opts.inSampleSize = scale;
						// System.out.println("lru=空,创建");
						// bitmap = BitmapFactory.decodeStream(is, null, opts);
						// saveBitmapToFile(bitmap, SDPATH);
						// System.out.println("宽="+bitmap.getWidth());
						// System.out.println("高="+bitmap.getHeight());
						// is.close();
						// conn.disconnect();
						// }else{
						// System.out.println("文件存在于SD卡上");
						// bitmap = downFile();
						// }
						lru.put(KEY, bitmap);
					} else {
						System.out.println("内存有文件");
						bitmap = (Bitmap) lru.get(KEY);
					}

				} catch (MalformedURLException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}

				return bitmap;
			}

			protected void onPostExecute(Bitmap bitmap1) {
				System.out.println("onPostExecute");
				iv.setImageBitmap(bitmap1);
			};

		}.execute(url);

	}
	private  byte[] toByteArray(InputStream input) throws IOException {
	    ByteArrayOutputStream output = new ByteArrayOutputStream();
	    byte[] buffer = new byte[4096];
	    int n = 0;
	    while (-1 != (n = input.read(buffer))) {
	        output.write(buffer, 0, n);
	    }
	    return output.toByteArray();
	}

	// private boolean downloadUrlToStream(String urlString,
	// OutputStream outputStream) {
	// HttpURLConnection urlConnection = null;
	// BufferedOutputStream out = null;
	// BufferedInputStream in = null;
	// try {
	// final URL url = new URL(urlString);
	// urlConnection = (HttpURLConnection) url.openConnection();
	// in = new BufferedInputStream(urlConnection.getInputStream(),
	// 8 * 1024);
	// out = new BufferedOutputStream(outputStream, 8 * 1024);
	// int b;
	// while ((b = in.read()) != -1) {
	// out.write(b);
	// }
	// return true;
	// } catch (final IOException e) {
	// e.printStackTrace();
	// } finally {
	// if (urlConnection != null) {
	// urlConnection.disconnect();
	// }
	// try {
	// if (out != null) {
	// out.close();
	// }
	// if (in != null) {
	// in.close();
	// }
	// } catch (final IOException e) {
	// e.printStackTrace();
	// }
	// }
	// return false;
	// }

//	public static void saveBitmapToFile(Bitmap bitmap, String _file)
//			throws IOException {
//		BufferedOutputStream os = null;
//		try {
//			File file = new File(_file);
//			// String _filePath_file.replace(File.separatorChar +
//			// file.getName(), "");
//			int end = _file.lastIndexOf(File.separator);
//			String _filePath = _file.substring(0, end);
//			File filePath = new File(_filePath);
//			if (!filePath.exists()) {
//				filePath.mkdirs();
//			}
//			file.createNewFile();
//			os = new BufferedOutputStream(new FileOutputStream(file));
//			bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
//		} finally {
//			if (os != null) {
//				try {
//					os.close();
//				} catch (IOException e) {
//				}
//			}
//		}
//	}
	// 获取当前要使用图片的比例值
	public int getScare(String url,byte[] bytes,Options opts1) {
		System.out.println("url="+url);
		try {
			// 不下载图片,只为了获取实际宽高
			opts1.inJustDecodeBounds = true;
			BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts1);
			int imageWidth = opts1.outWidth;
			int imageHeight = opts1.outHeight;
			System.out.println("imageWidth=" + opts1.outWidth);
			Display display = MainActivity.this.getWindowManager()
					.getDefaultDisplay();
			int screenWidth = display.getWidth();
			int screenHeight = display.getHeight();
			// 根据屏幕大小计算比例参数
			// int widthscale = imageWidth / screenWidth;
			// int heightscale = imageHeight / screenHeight;
			// 根据指定图片大小计算比例参数
			int widthscale = imageWidth / 200;
			int heightscale = imageHeight / 100;
			int scale = widthscale > heightscale ? widthscale : heightscale;
			System.out.println("scale="+scale);
			return scale;

		} catch (Exception e) {
			e.printStackTrace();
		}
		return 1;// 网络连接失败时默认返回1
	}

	// 传进字符串,转成md5码
	private String encrypByMd5(String context) {
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(context.getBytes());// update处理
			byte[] encryContext = md.digest();// 调用该方法完成计算

			int i;
			StringBuffer buf = new StringBuffer("");
			for (int offset = 0; offset < encryContext.length; offset++) {// 做相应的转化(十六进制)
				i = encryContext[offset];
				if (i < 0)
					i += 256;
				if (i < 16)
					buf.append("0");
				buf.append(Integer.toHexString(i));
			}
			return buf.toString();
			// System.out.println("32result: " + buf.toString());// 32位的加密
			// System.out.println("16result: " + buf.toString().substring(8,
			// 24));// 16位的加密
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return null;
	}

	class MyHandler extends Handler {
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			switch (msg.what) {
			case 0:
				// 测试用
				iv.setImageResource(R.drawable.ic_launcher);
				break;

			default:
				break;
			}
		}
	}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值