转子:https://software.intel.com/zh-cn/blogs/2014/02/20/android
在android应用开发的时候,加载网络图片是一个非常重要的部分,很多图片不可能放在本地,所以就必须要从服务器或者网络读取图片。
软引用是一个现在非常流行的方法,用户体验比较好,不用每次都需要从网络下载图片,如果下载后就存到本地,下次读取时首先查看本地有没有,如果没有再从网络读取。
记得2月份在和爱奇艺公司的项目总监一起搞联通的OTT盒子的时候他就提了一下软引用,奇艺做的手机客户端就是采用这种方法,所以你会发现奇艺客户端占用很大的空间,下面就分享一下异步加载网络图片的方法吧。
FileCache.java
- import java.io.File;
- import android.content.Context;
- public class FileCache {
- private File cacheDir;
- public FileCache(Context context) {
- // 找一个用来缓存图片的路径
- if (android.os.Environment.getExternalStorageState().equals(
- android.os.Environment.MEDIA_MOUNTED))
- cacheDir = new File(android.os.Environment.getExternalStorageDirectory(),
- "文件夹名称");
- else
- cacheDir = context.getCacheDir();
- if (!cacheDir.exists())
- cacheDir.mkdirs();
- }
- public File getFile(String url) {
- String filename = String.valueOf(url.hashCode());
- File f = new File(cacheDir, filename);
- return f;
- }
- public void clear() {
- File[] files = cacheDir.listFiles();
- if (files == null)
- return;
- for (File f : files)
- f.delete();
- }
- }
HttpUtil.java
- import java.io.ByteArrayOutputStream;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.io.UnsupportedEncodingException;
- import java.net.HttpURLConnection;
- import java.net.MalformedURLException;
- import java.net.ProtocolException;
- import java.net.URL;
- import java.net.URLEncoder;
- import java.util.Map;
- /**
- * Http 请求工具类
- *
- * @author Scorpio.Liu
- *
- */
- public class HttpUtil {
- /**
- * 获取响应字符串
- *
- * @param path
- * 路径
- * @param parameters
- * 参数
- * @return 响应字符串
- */
- public static String getResponseStr(String path, Map<String, String> parameters) {
- StringBuffer buffer = new StringBuffer();
- URL url;
- try {
- if (parameters != null && !parameters.isEmpty()) {
- for (Map.Entry<String, String> entry : parameters.entrySet()) {
- // 完成转码操作
- buffer.append(entry.getKey()).append("=")
- .append(URLEncoder.encode(entry.getValue(), "UTF-8")).append("&");
- }
- buffer.deleteCharAt(buffer.length() - 1);
- }
- url = new URL(path);
- HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
- urlConnection.setConnectTimeout(3000);
- urlConnection.setRequestMethod("POST");
- urlConnection.setDoInput(true);// 表示从服务器获取数据
- urlConnection.setDoOutput(true);// 表示向服务器写数据
- // 获得上传信息的字节大小以及长度
- byte[] mydata = buffer.toString().getBytes();
- // 表示设置请求体的类型是文本类型
- urlConnection.setRequestProperty("Content-Type",
- "application/x-www-form-urlencoded");
- urlConnection.setRequestProperty("Content-Length", String.valueOf(mydata.length));
- // 获得输出流,向服务器输出数据
- OutputStream outputStream = urlConnection.getOutputStream();
- outputStream.write(mydata, 0, mydata.length);
- outputStream.close();
- int responseCode = urlConnection.getResponseCode();
- if (responseCode == 200) {
- return changeInputStream(urlConnection.getInputStream());
- }
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- } catch (MalformedURLException e) {
- e.printStackTrace();
- } catch (ProtocolException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
- private static String changeInputStream(InputStream inputStream) {
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
- byte[] data = new byte[1024];
- int len = 0;
- String result = "";
- if (inputStream != null) {
- try {
- while ((len = inputStream.read(data)) != -1) {
- outputStream.write(data, 0, len);
- }
- result = new String(outputStream.toByteArray(), "UTF-8");
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return result;
- }
- public static InputStream getInputStream(String path) {
- URL url;
- try {
- url = new URL(path);
- HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
- urlConnection.setConnectTimeout(3000);
- urlConnection.setRequestMethod("GET");
- urlConnection.setDoInput(true);// 表示从服务器获取数据
- urlConnection.connect();
- if (urlConnection.getResponseCode() == 200)
- return urlConnection.getInputStream();
- } catch (MalformedURLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return null;
- }
- public static byte[] readStream(InputStream inStream) throws Exception {
- ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
- byte[] buffer = new byte[1024];
- int len = -1;
- while ((len = inStream.read(buffer)) != -1) {
- outSteam.write(buffer, 0, len);
- }
- outSteam.close();
- inStream.close();
- return outSteam.toByteArray();
- }
- public static void CopyStream(String url, File f) {
- FileOutputStream fileOutputStream = null;
- InputStream inputStream = null;
- try {
- inputStream = getInputStream(url);
- byte[] data = new byte[1024];
- int len = 0;
- fileOutputStream = new FileOutputStream(f);
- while ((len = inputStream.read(data)) != -1) {
- fileOutputStream.write(data, 0, len);
- }
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- if (inputStream != null) {
- try {
- inputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- if (fileOutputStream != null) {
- try {
- fileOutputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
- }
MemoryCache.java
- import java.lang.ref.SoftReference;
- import java.util.Collections;
- import java.util.HashMap;
- import java.util.Map;
- import android.graphics.Bitmap;
- public class MemoryCache {
- private Map<String, SoftReference<Bitmap>> cache = Collections
- .synchronizedMap(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();
- }
- }
ImageLoader.java
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.UnsupportedEncodingException;
- import java.net.URLEncoder;
- import java.util.Collections;
- import java.util.Map;
- import java.util.WeakHashMap;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import android.app.Activity;
- import android.content.Context;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.drawable.BitmapDrawable;
- import android.widget.ImageView;
- public class ImageLoader {
- private MemoryCache memoryCache = new MemoryCache();
- private FileCache fileCache;
- private Map<ImageView, String> imageViews = Collections
- .synchronizedMap(new WeakHashMap<ImageView, String>());
- private ExecutorService executorService;
- private boolean isSrc;
- /**
- * @param context
- * 上下文对象
- * @param flag
- * true为source资源,false为background资源
- */
- public ImageLoader(Context context, boolean flag) {
- fileCache = new FileCache(context);
- executorService = Executors.newFixedThreadPool(5);
- isSrc = flag;
- }
- final int stub_id = R.drawable.ic_launcher;
- public void DisplayImage(String url, ImageView imageView) {
- String u1 = url.substring(0, url.lastIndexOf("/") + 1);
- String u2 = url.substring(url.lastIndexOf("/") + 1);
- try {
- u2 = URLEncoder.encode(u2, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- url = u1 + u2;
- imageViews.put(imageView, url);
- Bitmap bitmap = memoryCache.get(url);
- if (bitmap != null) {
- if (isSrc)
- imageView.setImageBitmap(bitmap);
- else
- imageView.setBackgroundDrawable(new BitmapDrawable(bitmap));
- } else {
- queuePhoto(url, imageView);
- if (isSrc)
- imageView.setImageResource(stub_id);
- else
- imageView.setBackgroundResource(stub_id);
- }
- }
- private void queuePhoto(String url, ImageView imageView) {
- PhotoToLoad p = new PhotoToLoad(url, imageView);
- executorService.submit(new PhotosLoader(p));
- }
- private Bitmap getBitmap(String url) {
- try {
- File f = fileCache.getFile(url);
- // 从sd卡
- Bitmap b = onDecodeFile(f);
- if (b != null)
- return b;
- // 从网络
- Bitmap bitmap = null;
- System.out.println("ImageLoader-->download");
- HttpUtil.CopyStream(url, f);
- bitmap = onDecodeFile(f);
- return bitmap;
- } catch (Exception ex) {
- ex.printStackTrace();
- return null;
- }
- }
- public Bitmap onDecodeFile(File f) {
- try {
- return BitmapFactory.decodeStream(new FileInputStream(f));
- } catch (FileNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return null;
- }
- /**
- * 解码图像用来减少内存消耗
- *
- * @param f
- * @return
- */
- public Bitmap decodeFile(File f) {
- try {
- // 解码图像大小
- BitmapFactory.Options o = new BitmapFactory.Options();
- o.inJustDecodeBounds = true;
- BitmapFactory.decodeStream(new FileInputStream(f), null, o);
- // 找到正确的刻度值,它应该是2的幂。
- final int REQUIRED_SIZE = 70;
- int width_tmp = o.outWidth, height_tmp = o.outHeight;
- int scale = 1;
- while (true) {
- if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE)
- break;
- width_tmp /= 2;
- height_tmp /= 2;
- scale *= 2;
- }
- BitmapFactory.Options o2 = new BitmapFactory.Options();
- o2.inSampleSize = scale;
- return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
- } catch (FileNotFoundException e) {
- }
- return null;
- }
- /**
- * 任务队列
- *
- * @author Scorpio.Liu
- *
- */
- private class PhotoToLoad {
- public String url;
- public ImageView imageView;
- public PhotoToLoad(String u, ImageView i) {
- url = u;
- imageView = i;
- }
- }
- class PhotosLoader implements Runnable {
- PhotoToLoad photoToLoad;
- PhotosLoader(PhotoToLoad photoToLoad) {
- this.photoToLoad = photoToLoad;
- }
- @Override
- public void run() {
- if (imageViewReused(photoToLoad))
- return;
- Bitmap bmp = getBitmap(photoToLoad.url);
- memoryCache.put(photoToLoad.url, bmp);
- if (imageViewReused(photoToLoad))
- return;
- BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad);
- Activity a = (Activity) photoToLoad.imageView.getContext();
- a.runOnUiThread(bd);
- }
- }
- boolean imageViewReused(PhotoToLoad photoToLoad) {
- String tag = imageViews.get(photoToLoad.imageView);
- if (tag == null || !tag.equals(photoToLoad.url))
- return true;
- return false;
- }
- /**
- * 显示位图在UI线程
- *
- * @author Scorpio.Liu
- *
- */
- class BitmapDisplayer implements Runnable {
- Bitmap bitmap;
- PhotoToLoad photoToLoad;
- public BitmapDisplayer(Bitmap b, PhotoToLoad p) {
- bitmap = b;
- photoToLoad = p;
- }
- public void run() {
- if (imageViewReused(photoToLoad))
- return;
- if (bitmap != null) {
- if (isSrc)
- photoToLoad.imageView.setImageBitmap(bitmap);
- else
- photoToLoad.imageView.setBackgroundDrawable(new BitmapDrawable(bitmap));
- } else {
- if (isSrc)
- photoToLoad.imageView.setImageResource(stub_id);
- else
- photoToLoad.imageView.setBackgroundResource(stub_id);
- }
- }
- }
- public void clearCache() {
- memoryCache.clear();
- fileCache.clear();
- }
- }
使用的时候用ImageLoader这个类就ok了,很方便~