Android实现图片异步加载并缓存到本地_Android

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

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

下面就分享一下异步加载网络图片的方法吧。

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

希望本文所述对大家学习Android软件编程有所帮助。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索easyui异步加载树实现、ajax怎么实现异步加载、ios 异步加载本地图片、js实现异步加载、jsp实现异步加载,以便于您获取更多的相关知识。

时间: 2024-08-26 08:43:09

Android实现图片异步加载并缓存到本地_Android的相关文章

Android实现图片异步加载并缓存到本地

在android应用开发的时候,加载网络图片是一个非常重要的部分,很多图片不可能放在本地,所以就必须要从服务器或者网络读取图片. 软引用是一个现在非常流行的方法,用户体验比较好,不用每次都需要从网络下载图片,如果下载后就存到本地,下次读取时首先查看本地有没有,如果没有再从网络读取. 下面就分享一下异步加载网络图片的方法吧. FileCache.java import java.io.File; import android.content.Context; public class FileCa

Android实现图片异步加载及本地缓存_Android

在android项目中访问网络图片是非常普遍性的事情,如果我们每次请求都要访问网络来获取图片,会非常耗费流量,而且图片占用内存空间也比较大,图片过多且不释放的话很容易造成内存溢出.针对上面遇到的两个问题,首先耗费流量我们可以将图片第一次加载上面缓存到本地,以后如果本地有就直接从本地加载.图片过多造成内存溢出,这个是最不容易解决的,要想一些好的缓存策略,比如大图片使用LRU缓存策略或懒加载缓存策略,首先介绍一下本地缓存图片. 首先看一下异步加载缓存本地代码: public class AsyncB

Android实现图片异步加载及本地缓存

在android项目中访问网络图片是非常普遍性的事情,如果我们每次请求都要访问网络来获取图片,会非常耗费流量,而且图片占用内存空间也比较大,图片过多且不释放的话很容易造成内存溢出.针对上面遇到的两个问题,首先耗费流量我们可以将图片第一次加载上面缓存到本地,以后如果本地有就直接从本地加载.图片过多造成内存溢出,这个是最不容易解决的,要想一些好的缓存策略,比如大图片使用LRU缓存策略或懒加载缓存策略,首先介绍一下本地缓存图片. 首先看一下异步加载缓存本地代码: public class AsyncB

Android-Universal-Image-Loader图片异步加载并缓存

 这个图片异步加载并缓存的类已经被很多开发者所使用,是最常用的几个开源库之一,主流的应用,随便反编译几个火的项目,都可以见到它的身影.        可是有的人并不知道如何去使用这库如何进行配置,网上查到的信息对于刚接触的人来说可能太少了,下面我就把我使用过程中所知道的写了下来,希望可以帮助自己和别人更深入了解这个库的使用和配置.          GITHUB上的下载路径为:https://github.com/nostra13/Android-Universal-Image-Loader ,

Android图片异步加载框架Android-Universal-Image-Loader

Android-Universal-Image-Loader是一个图片异步加载,缓存和显示的框架.这个框架已经被很多开发者所使用,是最常用的几个Android开源项目之一,主流的应用,随便反编译几个,都可以见到它的身影.淘宝,天猫,Facebook,京东商城等都用到了这个项目.该项目的Github地址链接:https://github.com/nostra13/Android-Universal-Image-Loader 运行流程:每一个图片的加载和显示任务都运行在独立的线程中,除非这个图片缓存

listview-Android ListView图片异步加载和上拉加载

问题描述 Android ListView图片异步加载和上拉加载 我的ListView设置一个OnScrollListener,然后更加可见的item数目来异步加载图片,和缓存图片, 但同时这个ListView又是个第三方的带上拉加载的,第三方的代码里也注册了OnScrollListener, 因此这两个OnScrollListener,只能有一个生效,但我想把上拉加载和异步加载图片的逻辑, 都写在同一个OnScrollListener,有什么好的设计吗? 问题在于上拉加载是在第三方的库中,而异

Android-Universal-Image-Loader 图片异步加载类库的使用(超详细配置)

       这个图片异步加载并缓存的类已经被很多开发者所使用,是最常用的几个开源库之一,主流的应用,随便反编译几个火的项目,都可以见到它的身影.        可是有的人并不知道如何去使用这库如何进行配置,网上查到的信息对于刚接触的人来说可能太少了,下面我就把我使用过程中所知道的写了下来,希望可以帮助自己和别人更深入了解这个库的使用和配置.          GITHUB上的下载路径为:https://github.com/nostra13/Android-Universal-Image-Lo

Android-Universal-Image-Loader 图片异步加载类库的使用

在博客中看到一篇利用组件进行图片异步加载的文章在此作记录 原文:http://blog.csdn.net/vipzjyno1/article/details/23206387 这个图片异步加载并缓存的类已经被很多开发者所使用,是最常用的几个开源库之一,主流的应用,随便反编译几个火的项目,都可以见到它的身影.        可是有的人并不知道如何去使用这库如何进行配置,网上查到的信息对于刚接触的人来说可能太少了,下面我就把我使用过程中所知道的写了下来,希望可以帮助自己和别人更深入了解这个库的使用和

Android优化双缓存的图片异步加载工具(LruCache+SoftReference)

之前在郭大神的博客看到使用LruCache算法实现图片缓存的.这里仿效他的思路,自己也写了一个. 并加入ConcurrentHashMap<String, SoftReference<Bitmap>>去实现二级缓存,因为ConcurrentHashMap是多个锁的线程安全,支持高并发.很适合这种频繁访问读取内存的操作. 下面整个思路是,使用了系统提供的LruCache类做一级缓存, 大小为运行内存的1/8,当LruCache容量要满的时候,会自动将系统移除的图片放到二级缓存中,但为