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软件编程有所帮助。

时间: 2024-09-15 03:53:46

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容量要满的时候,会自动将系统移除的图片放到二级缓存中,但为