我的位置: 首页 > 学习专区 > 安卓技术 > Android 异步加载网络图片并缓存到本地

Android 异步加载网络图片并缓存到本地

2014-08-19 14:21:12
来源:
[导读]   在android应用开发的时候,加载网络图片是一个非常重要的部分,很多图片不可能放在本地,所以就必须要从服务器或者网络读取图片。  

  在android应用开发的时候,加载网络图片是一个非常重要的部分,很多图片不可能放在本地,所以就必须要从服务器或者网络读取图片。

  软引用是一个现在非常流行的方法,用户体验比较好,不用每次都需要从网络下载图片,如果下载后就存到本地,下次读取时首先查看本地有没有,如果没有再从网络读取。

  记得2月份在和爱奇艺公司的项目总监一起搞联通的OTT盒子的时候他就提了一下软引用,奇艺做的手机客户端就是采用这种方法,所以你会发现奇艺客户端占用很大的空间,下面就分享一下异步加载网络图片的方法吧。

  FileCache.java

  [java] view plaincopy

  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

  [java] view plaincopy

  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 parameters) {

  StringBuffer buffer = new StringBuffer();

  URL url;

  try {

  if (parameters != null && !parameters.isEmpty()) {

  for (Map.Entry 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

  [java] view plaincopy

  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> cache = Collections

  .synchronizedMap(new HashMap>());// 软引用

  public Bitmap get(String id) {

  if (!cache.containsKey(id))

  return null;

  SoftReference ref = cache.get(id);

  return ref.get();

  }

  public void put(String id, Bitmap bitmap) {

  cache.put(id, new SoftReference(bitmap));

  }

  public void clear() {

  cache.clear();

  }

  }

  ImageLoader.java

  [java] view plaincopy

  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 imageViews = Collections

  .synchronizedMap(new WeakHashMap());

  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了,很方便~

评论
热点专题
>>
相关文章推荐
>>