400-696-8028

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

长沙北大青鸟作者:科泰校区

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

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

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

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

 

FileCache.java

 

[java] view plaincopy
 
  1. import java.io.File;  

  2. import android.content.Context;  

  3.  

  4. public class FileCache {  

  5.  

  6.    private File cacheDir;  

  7.  

  8.    public FileCache(Context context) {  

  9.        // 找一个用来缓存图片的路径  

  10.        if (android.os.Environment.getExternalStorageState().equals(  

  11.                android.os.Environment.MEDIA_MOUNTED))  

  12.            cacheDir = new File(android.os.Environment.getExternalStorageDirectory(),  

  13.                    "文件夹名称");  

  14.        else  

  15.            cacheDir = context.getCacheDir();  

  16.        if (!cacheDir.exists())  

  17.            cacheDir.mkdirs();  

  18.    }  

  19.  

  20.    public File getFile(String url) {  

  21.        String filename = String.valueOf(url.hashCode());  

  22.        File f = new File(cacheDir, filename);  

  23.        return f;  

  24.    }  

  25.  

  26.    public void clear() {  

  27.        File[] files = cacheDir.listFiles();  

  28.        if (files == null)  

  29.            return;  

  30.        for (File f : files)  

  31.            f.delete();  

  32.    }  

  33.  

  34. }  

 

 

HttpUtil.java

 

[java] view plaincopy
 
  1. import java.io.ByteArrayOutputStream;  

  2. import java.io.File;  

  3. import java.io.FileNotFoundException;  

  4. import java.io.FileOutputStream;  

  5. import java.io.IOException;  

  6. import java.io.InputStream;  

  7. import java.io.OutputStream;  

  8. import java.io.UnsupportedEncodingException;  

  9. import java.net.HttpURLConnection;  

  10. import java.net.MalformedURLException;  

  11. import java.net.ProtocolException;  

  12. import java.net.URL;  

  13. import java.net.URLEncoder;  

  14. import java.util.Map;  

  15.  

  16. /**

  17. * Http 请求工具类

  18. *  

  19. * @author Scorpio.Liu

  20. *  

  21. */  

  22. public class HttpUtil {  

  23.  

  24.    /**

  25.     * 获取响应字符串

  26.     *  

  27.     * @param path

  28.     *            路径

  29.     * @param parameters

  30.     *            参数

  31.     * @return 响应字符串

  32.     */  

  33.    public static String getResponseStr(String path, Map<String, String> parameters) {  

  34.        StringBuffer buffer = new StringBuffer();  

  35.        URL url;  

  36.        try {  

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

  38.                for (Map.Entry<String, String> entry : parameters.entrySet()) {  

  39.                    // 完成转码操作  

  40.                    buffer.append(entry.getKey()).append("=")  

  41.                            .append(URLEncoder.encode(entry.getValue(), "UTF-8")).append("&");  

  42.                }  

  43.                buffer.deleteCharAt(buffer.length() - 1);  

  44.            }  

  45.            url = new URL(path);  

  46.            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();  

  47.            urlConnection.setConnectTimeout(3000);  

  48.            urlConnection.setRequestMethod("POST");  

  49.            urlConnection.setDoInput(true);// 表示从服务器获取数据  

  50.            urlConnection.setDoOutput(true);// 表示向服务器写数据  

  51.            // 获得上传信息的字节大小以及长度  

  52.            byte[] mydata = buffer.toString().getBytes();  

  53.            // 表示设置请求体的类型是文本类型  

  54.            urlConnection.setRequestProperty("Content-Type",  

  55.                    "application/x-www-form-urlencoded");  

  56.            urlConnection.setRequestProperty("Content-Length", String.valueOf(mydata.length));  

  57.            // 获得输出流,向服务器输出数据  

  58.            OutputStream outputStream = urlConnection.getOutputStream();  

  59.            outputStream.write(mydata, 0, mydata.length);  

  60.            outputStream.close();  

  61.            int responseCode = urlConnection.getResponseCode();  

  62.            if (responseCode == 200) {  

  63.                return changeInputStream(urlConnection.getInputStream());  

  64.            }  

  65.        } catch (UnsupportedEncodingException e) {  

  66.            e.printStackTrace();  

  67.        } catch (MalformedURLException e) {  

  68.            e.printStackTrace();  

  69.        } catch (ProtocolException e) {  

  70.            e.printStackTrace();  

  71.        } catch (IOException e) {  

  72.            e.printStackTrace();  

  73.        }  

  74.        return null;  

  75.    }  

  76.  

  77.    private static String changeInputStream(InputStream inputStream) {  

  78.        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();  

  79.        byte[] data = new byte[1024];  

  80.        int len = 0;  

  81.        String result = "";  

  82.        if (inputStream != null) {  

  83.            try {  

  84.                while ((len = inputStream.read(data)) != -1) {  

  85.                    outputStream.write(data, 0, len);  

  86.                }  

  87.                result = new String(outputStream.toByteArray(), "UTF-8");  

  88.            } catch (IOException e) {  

  89.                e.printStackTrace();  

  90.            }  

  91.        }  

  92.        return result;  

  93.    }  

  94.  

  95.    public static InputStream getInputStream(String path) {  

  96.        URL url;  

  97.        try {  

  98.            url = new URL(path);  

  99.            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();  

  100.            urlConnection.setConnectTimeout(3000);  

  101.            urlConnection.setRequestMethod("GET");  

  102.            urlConnection.setDoInput(true);// 表示从服务器获取数据  

  103.            urlConnection.connect();  

  104.            if (urlConnection.getResponseCode() == 200)  

  105.                return urlConnection.getInputStream();  

  106.        } catch (MalformedURLException e) {  

  107.            // TODO Auto-generated catch block  

  108.            e.printStackTrace();  

  109.        } catch (IOException e) {  

  110.            // TODO Auto-generated catch block  

  111.            e.printStackTrace();  

  112.        } catch (Exception e) {  

  113.            // TODO Auto-generated catch block  

  114.            e.printStackTrace();  

  115.        }  

  116.        return null;  

  117.    }  

  118.  

  119.    public static byte[] readStream(InputStream inStream) throws Exception {  

  120.        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();  

  121.        byte[] buffer = new byte[1024];  

  122.        int len = -1;  

  123.        while ((len = inStream.read(buffer)) != -1) {  

  124.            outSteam.write(buffer, 0, len);  

  125.  

  126.        }  

  127.        outSteam.close();  

  128.        inStream.close();  

  129.        return outSteam.toByteArray();  

  130.    }  

  131.  

  132.    public static void CopyStream(String url, File f) {  

  133.        FileOutputStream fileOutputStream = null;  

  134.        InputStream inputStream = null;  

  135.        try {  

  136.            inputStream = getInputStream(url);  

  137.            byte[] data = new byte[1024];  

  138.            int len = 0;  

  139.            fileOutputStream = new FileOutputStream(f);  

  140.            while ((len = inputStream.read(data)) != -1) {  

  141.                fileOutputStream.write(data, 0, len);  

  142.            }  

  143.        } catch (FileNotFoundException e) {  

  144.            e.printStackTrace();  

  145.        } catch (IOException e) {  

  146.            e.printStackTrace();  

  147.        } finally {  

  148.            if (inputStream != null) {  

  149.                try {  

  150.                    inputStream.close();  

  151.                } catch (IOException e) {  

  152.                    e.printStackTrace();  

  153.                }  

  154.            }  

  155.            if (fileOutputStream != null) {  

  156.                try {  

  157.                    fileOutputStream.close();  

  158.                } catch (IOException e) {  

  159.                    e.printStackTrace();  

  160.                }  

  161.            }  

  162.        }  

  163.    }  

  164.  

  165. }  


MemoryCache.java

 

 

[java] view plaincopy
 
  1. import java.lang.ref.SoftReference;  

  2. import java.util.Collections;  

  3. import java.util.HashMap;  

  4. import java.util.Map;  

  5. import android.graphics.Bitmap;  

  6.  

  7. public class MemoryCache {  

  8.    private Map<String, SoftReference<Bitmap>> cache = Collections  

  9.            .synchronizedMap(new HashMap<String, SoftReference<Bitmap>>());// 软引用  

  10.  

  11.    public Bitmap get(String id) {  

  12.        if (!cache.containsKey(id))  

  13.            return null;  

  14.        SoftReference<Bitmap> ref = cache.get(id);  

  15.        return ref.get();  

  16.    }  

  17.  

  18.    public void put(String id, Bitmap bitmap) {  

  19.        cache.put(id, new SoftReference<Bitmap>(bitmap));  

  20.    }  

  21.  

  22.    public void clear() {  

  23.        cache.clear();  

  24.    }  

  25. }  


ImageLoader.java

 

 

[java] view plaincopy
 
  1. import java.io.File;  

  2. import java.io.FileInputStream;  

  3. import java.io.FileNotFoundException;  

  4. import java.io.UnsupportedEncodingException;  

  5. import java.net.URLEncoder;  

  6. import java.util.Collections;  

  7. import java.util.Map;  

  8. import java.util.WeakHashMap;  

  9. import java.util.concurrent.ExecutorService;  

  10. import java.util.concurrent.Executors;  

  11. import android.app.Activity;  

  12. import android.content.Context;  

  13. import android.graphics.Bitmap;  

  14. import android.graphics.BitmapFactory;  

  15. import android.graphics.drawable.BitmapDrawable;  

  16. import android.widget.ImageView;  

  17.  

  18. public class ImageLoader {  

  19.  

  20.    private MemoryCache memoryCache = new MemoryCache();  

  21.    private FileCache fileCache;  

  22.    private Map<ImageView, String> imageViews = Collections  

  23.            .synchronizedMap(new WeakHashMap<ImageView, String>());  

  24.    private ExecutorService executorService;  

  25.    private boolean isSrc;  

  26.  

  27.    /**

  28.     * @param context

  29.     *            上下文对象

  30.     * @param flag

  31.     *            true为source资源,false为background资源

  32.     */  

  33.    public ImageLoader(Context context, boolean flag) {  

  34.        fileCache = new FileCache(context);  

  35.        executorService = Executors.newFixedThreadPool(5);  

  36.        isSrc = flag;  

  37.    }  

  38.  

  39.    final int stub_id = R.drawable.ic_launcher;  

  40.  

  41.    public void DisplayImage(String url, ImageView imageView) {  

  42.        String u1 = url.substring(0, url.lastIndexOf("/") + 1);  

  43.        String u2 = url.substring(url.lastIndexOf("/") + 1);  

  44.        try {  

  45.            u2 = URLEncoder.encode(u2, "UTF-8");  

  46.        } catch (UnsupportedEncodingException e) {  

  47.            e.printStackTrace();  

  48.        }  

  49.        url = u1 + u2;  

  50.        imageViews.put(imageView, url);  

  51.        Bitmap bitmap = memoryCache.get(url);  

  52.        if (bitmap != null) {  

  53.            if (isSrc)  

  54.                imageView.setImageBitmap(bitmap);  

  55.            else  

  56.                imageView.setBackgroundDrawable(new BitmapDrawable(bitmap));  

  57.        } else {  

  58.            queuePhoto(url, imageView);  

  59.            if (isSrc)  

  60.                imageView.setImageResource(stub_id);  

  61.            else  

  62.                imageView.setBackgroundResource(stub_id);  

  63.        }  

  64.    }  

  65.  

  66.    private void queuePhoto(String url, ImageView imageView) {  

  67.        PhotoToLoad p = new PhotoToLoad(url, imageView);  

  68.        executorService.submit(new PhotosLoader(p));  

  69.    }  

  70.  

  71.    private Bitmap getBitmap(String url) {  

  72.        try {  

  73.            File f = fileCache.getFile(url);  

  74.            // 从sd卡  

  75.            Bitmap b = onDecodeFile(f);  

  76.            if (b != null)  

  77.                return b;  

  78.            // 从网络  

  79.            Bitmap bitmap = null;  

  80.            System.out.println("ImageLoader-->download");  

  81.            HttpUtil.CopyStream(url, f);  

  82.            bitmap = onDecodeFile(f);  

  83.  

  84.            return bitmap;  

  85.        } catch (Exception ex) {  

  86.            ex.printStackTrace();  

  87.            return null;  

  88.        }  

  89.    }  

  90.  

  91.    public Bitmap onDecodeFile(File f) {  

  92.        try {  

  93.            return BitmapFactory.decodeStream(new FileInputStream(f));  

  94.        } catch (FileNotFoundException e) {  

  95.            // TODO Auto-generated catch block  

  96.            e.printStackTrace();  

  97.        }  

  98.        return null;  

  99.    }  

  100.  

  101.    /**

  102.     * 解码图像用来减少内存消耗

  103.     *  

  104.     * @param f

  105.     * @return

  106.     */  

  107.    public Bitmap decodeFile(File f) {  

  108.        try {  

  109.            // 解码图像大小  

  110.            BitmapFactory.Options o = new BitmapFactory.Options();  

  111.            o.inJustDecodeBounds = true;  

  112.            BitmapFactory.decodeStream(new FileInputStream(f), null, o);  

  113.            // 找到正确的刻度值,它应该是2的幂。  

  114.            final int REQUIRED_SIZE = 70;  

  115.            int width_tmp = o.outWidth, height_tmp = o.outHeight;  

  116.            int scale = 1;  

  117.            while (true) {  

  118.                if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE)  

  119.                    break;  

  120.                width_tmp /= 2;  

  121.                height_tmp /= 2;  

  122.                scale *= 2;  

  123.            }  

  124.            BitmapFactory.Options o2 = new BitmapFactory.Options();  

  125.            o2.inSampleSize = scale;  

  126.            return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);  

  127.        } catch (FileNotFoundException e) {  

  128.        }  

  129.        return null;  

  130.    }  

  131.  

  132.    /**

  133.     * 任务队列

  134.     *  

  135.     * @author Scorpio.Liu

  136.     *  

  137.     */  

  138.    private class PhotoToLoad {  

  139.        public String url;  

  140.        public ImageView imageView;  

  141.  

  142.        public PhotoToLoad(String u, ImageView i) {  

  143.            url = u;  

  144.            imageView = i;  

  145.        }  

  146.    }  

  147.  

  148.    class PhotosLoader implements Runnable {  

  149.        PhotoToLoad photoToLoad;  

  150.  

  151.        PhotosLoader(PhotoToLoad photoToLoad) {  

  152.            this.photoToLoad = photoToLoad;  

  153.        }  

  154.  

  155.        @Override  

  156.        public void run() {  

  157.            if (imageViewReused(photoToLoad))  

  158.                return;  

  159.            Bitmap bmp = getBitmap(photoToLoad.url);  

  160.            memoryCache.put(photoToLoad.url, bmp);  

  161.            if (imageViewReused(photoToLoad))  

  162.                return;  

  163.            BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad);  

  164.            Activity a = (Activity) photoToLoad.imageView.getContext();  

  165.            a.runOnUiThread(bd);  

  166.        }  

  167.    }  

  168.  

  169.    boolean imageViewReused(PhotoToLoad photoToLoad) {  

  170.        String tag = imageViews.get(photoToLoad.imageView);  

  171.        if (tag == null || !tag.equals(photoToLoad.url))  

  172.            return true;  

  173.        return false;  

  174.    }  

  175.  

  176.    /**

  177.     * 显示位图在UI线程

  178.     *  

  179.     * @author Scorpio.Liu

  180.     *  

  181.     */  

  182.    class BitmapDisplayer implements Runnable {  

  183.        Bitmap bitmap;  

  184.        PhotoToLoad photoToLoad;  

  185.  

  186.        public BitmapDisplayer(Bitmap b, PhotoToLoad p) {  

  187.            bitmap = b;  

  188.            photoToLoad = p;  

  189.        }  

  190.  

  191.        public void run() {  

  192.            if (imageViewReused(photoToLoad))  

  193.                return;  

  194.            if (bitmap != null) {  

  195.                if (isSrc)  

  196.                    photoToLoad.imageView.setImageBitmap(bitmap);  

  197.                else  

  198.                    photoToLoad.imageView.setBackgroundDrawable(new BitmapDrawable(bitmap));  

  199.            } else {  

  200.                if (isSrc)  

  201.                    photoToLoad.imageView.setImageResource(stub_id);  

  202.                else  

  203.                    photoToLoad.imageView.setBackgroundResource(stub_id);  

  204.            }  

  205.        }  

  206.    }  

  207.  

  208.    public void clearCache() {  

  209.        memoryCache.clear();  

  210.        fileCache.clear();  

  211.    }  

  212.  

  213. }  


使用的时候用ImageLoader这个类就ok了,很方便~

 
关于我们
公司简介
发展历程
青鸟荣誉
联系我们
加入我们
青鸟课程
BCVE视频特效课程
BCUI全链路UI设计
BCSP软件开发专业
BCNT网络工程师
启能职业教育基础课程
长沙初中生学什么
长沙高中生学什么
长沙大学生学什么