首页 > 系统 > Android > 正文

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

2020-04-11 10:47:31
字体:
来源:转载
供稿:网友

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表