zoukankan      html  css  js  c++  java
  • Android编程之图片(异步)加载类

    应某人之请,写一篇关于图片加载类。其实,网上有很多这样的类,而且比较推崇的是来自google中开源中的一篇。他写的比较好了,而且注意了内存优化,下面贴出它的图片下载类:

    [java] view plaincopy
     
    1. /* 
    2.  * Copyright (C) 2010 The Android Open Source Project 
    3.  * 
    4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
    5.  * you may not use this file except in compliance with the License. 
    6.  * You may obtain a copy of the License at 
    7.  * 
    8.  *      http://www.apache.org/licenses/LICENSE-2.0 
    9.  * 
    10.  * Unless required by applicable law or agreed to in writing, software 
    11.  * distributed under the License is distributed on an "AS IS" BASIS, 
    12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
    13.  * See the License for the specific language governing permissions and 
    14.  * limitations under the License. 
    15.  */  
    16.   
    17. package com.example.android.imagedownloader;  
    18.   
    19. import org.apache.http.HttpEntity;  
    20. import org.apache.http.HttpResponse;  
    21. import org.apache.http.HttpStatus;  
    22. import org.apache.http.client.HttpClient;  
    23. import org.apache.http.client.methods.HttpGet;  
    24. import org.apache.http.impl.client.DefaultHttpClient;  
    25.   
    26. import android.graphics.Bitmap;  
    27. import android.graphics.BitmapFactory;  
    28. import android.graphics.Color;  
    29. import android.graphics.drawable.ColorDrawable;  
    30. import android.graphics.drawable.Drawable;  
    31. import android.net.http.AndroidHttpClient;  
    32. import android.os.AsyncTask;  
    33. import android.os.Handler;  
    34. import android.util.Log;  
    35. import android.widget.ImageView;  
    36.   
    37. import java.io.FilterInputStream;  
    38. import java.io.IOException;  
    39. import java.io.InputStream;  
    40. import java.lang.ref.SoftReference;  
    41. import java.lang.ref.WeakReference;  
    42. import java.util.HashMap;  
    43. import java.util.LinkedHashMap;  
    44. import java.util.concurrent.ConcurrentHashMap;  
    45.   
    46. /** 
    47.  * This helper class download images from the Internet and binds those with the provided ImageView. 
    48.  * 
    49.  * <p>It requires the INTERNET permission, which should be added to your application's manifest 
    50.  * file.</p> 
    51.  * 
    52.  * A local cache of downloaded images is maintained internally to improve performance. 
    53.  */  
    54. public class ImageDownloader {  
    55.     private static final String LOG_TAG = "ImageDownloader";  
    56.   
    57.     public enum Mode { NO_ASYNC_TASK, NO_DOWNLOADED_DRAWABLE, CORRECT }  
    58.     private Mode mode = Mode.NO_ASYNC_TASK;  
    59.       
    60.     /** 
    61.      * Download the specified image from the Internet and binds it to the provided ImageView. The 
    62.      * binding is immediate if the image is found in the cache and will be done asynchronously 
    63.      * otherwise. A null bitmap will be associated to the ImageView if an error occurs. 
    64.      * 
    65.      * @param url The URL of the image to download. 
    66.      * @param imageView The ImageView to bind the downloaded image to. 
    67.      */  
    68.     public void download(String url, ImageView imageView) {  
    69.         resetPurgeTimer();  
    70.         Bitmap bitmap = getBitmapFromCache(url);  
    71.   
    72.         if (bitmap == null) {  
    73.             forceDownload(url, imageView);  
    74.         } else {  
    75.             cancelPotentialDownload(url, imageView);  
    76.             imageView.setImageBitmap(bitmap);  
    77.         }  
    78.     }  
    79.   
    80.     /* 
    81.      * Same as download but the image is always downloaded and the cache is not used. 
    82.      * Kept private at the moment as its interest is not clear. 
    83.        private void forceDownload(String url, ImageView view) { 
    84.           forceDownload(url, view, null); 
    85.        } 
    86.      */  
    87.   
    88.     /** 
    89.      * Same as download but the image is always downloaded and the cache is not used. 
    90.      * Kept private at the moment as its interest is not clear. 
    91.      */  
    92.     private void forceDownload(String url, ImageView imageView) {  
    93.         // State sanity: url is guaranteed to never be null in DownloadedDrawable and cache keys.  
    94.         if (url == null) {  
    95.             imageView.setImageDrawable(null);  
    96.             return;  
    97.         }  
    98.   
    99.         if (cancelPotentialDownload(url, imageView)) {  
    100.             switch (mode) {  
    101.                 case NO_ASYNC_TASK:  
    102.                     Bitmap bitmap = downloadBitmap(url);  
    103.                     addBitmapToCache(url, bitmap);  
    104.                     imageView.setImageBitmap(bitmap);  
    105.                     break;  
    106.   
    107.                 case NO_DOWNLOADED_DRAWABLE:  
    108.                     imageView.setMinimumHeight(156);  
    109.                     BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);  
    110.                     task.execute(url);  
    111.                     break;  
    112.   
    113.                 case CORRECT:  
    114.                     task = new BitmapDownloaderTask(imageView);  
    115.                     DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);  
    116.                     imageView.setImageDrawable(downloadedDrawable);  
    117.                     imageView.setMinimumHeight(156);  
    118.                     task.execute(url);  
    119.                     break;  
    120.             }  
    121.         }  
    122.     }  
    123.   
    124.     /** 
    125.      * Returns true if the current download has been canceled or if there was no download in 
    126.      * progress on this image view. 
    127.      * Returns false if the download in progress deals with the same url. The download is not 
    128.      * stopped in that case. 
    129.      */  
    130.     private static boolean cancelPotentialDownload(String url, ImageView imageView) {  
    131.         BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);  
    132.   
    133.         if (bitmapDownloaderTask != null) {  
    134.             String bitmapUrl = bitmapDownloaderTask.url;  
    135.             if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {  
    136.                 bitmapDownloaderTask.cancel(true);  
    137.             } else {  
    138.                 // The same URL is already being downloaded.  
    139.                 return false;  
    140.             }  
    141.         }  
    142.         return true;  
    143.     }  
    144.   
    145.     /** 
    146.      * @param imageView Any imageView 
    147.      * @return Retrieve the currently active download task (if any) associated with this imageView. 
    148.      * null if there is no such task. 
    149.      */  
    150.     private static BitmapDownloaderTask getBitmapDownloaderTask(ImageView imageView) {  
    151.         if (imageView != null) {  
    152.             Drawable drawable = imageView.getDrawable();  
    153.             if (drawable instanceof DownloadedDrawable) {  
    154.                 DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;  
    155.                 return downloadedDrawable.getBitmapDownloaderTask();  
    156.             }  
    157.         }  
    158.         return null;  
    159.     }  
    160.   
    161.     Bitmap downloadBitmap(String url) {  
    162.         final int IO_BUFFER_SIZE = 4 * 1024;  
    163.   
    164.         // AndroidHttpClient is not allowed to be used from the main thread  
    165.         final HttpClient client = (mode == Mode.NO_ASYNC_TASK) ? new DefaultHttpClient() :  
    166.             AndroidHttpClient.newInstance("Android");  
    167.         final HttpGet getRequest = new HttpGet(url);  
    168.   
    169.         try {  
    170.             HttpResponse response = client.execute(getRequest);  
    171.             final int statusCode = response.getStatusLine().getStatusCode();  
    172.             if (statusCode != HttpStatus.SC_OK) {  
    173.                 Log.w("ImageDownloader", "Error " + statusCode +  
    174.                         " while retrieving bitmap from " + url);  
    175.                 return null;  
    176.             }  
    177.   
    178.             final HttpEntity entity = response.getEntity();  
    179.             if (entity != null) {  
    180.                 InputStream inputStream = null;  
    181.                 try {  
    182.                     inputStream = entity.getContent();  
    183.                     // return BitmapFactory.decodeStream(inputStream);  
    184.                     // Bug on slow connections, fixed in future release.  
    185.                     return BitmapFactory.decodeStream(new FlushedInputStream(inputStream));  
    186.                 } finally {  
    187.                     if (inputStream != null) {  
    188.                         inputStream.close();  
    189.                     }  
    190.                     entity.consumeContent();  
    191.                 }  
    192.             }  
    193.         } catch (IOException e) {  
    194.             getRequest.abort();  
    195.             Log.w(LOG_TAG, "I/O error while retrieving bitmap from " + url, e);  
    196.         } catch (IllegalStateException e) {  
    197.             getRequest.abort();  
    198.             Log.w(LOG_TAG, "Incorrect URL: " + url);  
    199.         } catch (Exception e) {  
    200.             getRequest.abort();  
    201.             Log.w(LOG_TAG, "Error while retrieving bitmap from " + url, e);  
    202.         } finally {  
    203.             if ((client instanceof AndroidHttpClient)) {  
    204.                 ((AndroidHttpClient) client).close();  
    205.             }  
    206.         }  
    207.         return null;  
    208.     }  
    209.   
    210.     /* 
    211.      * An InputStream that skips the exact number of bytes provided, unless it reaches EOF. 
    212.      */  
    213.     static class FlushedInputStream extends FilterInputStream {  
    214.         public FlushedInputStream(InputStream inputStream) {  
    215.             super(inputStream);  
    216.         }  
    217.   
    218.         @Override  
    219.         public long skip(long n) throws IOException {  
    220.             long totalBytesSkipped = 0L;  
    221.             while (totalBytesSkipped < n) {  
    222.                 long bytesSkipped = in.skip(n - totalBytesSkipped);  
    223.                 if (bytesSkipped == 0L) {  
    224.                     int b = read();  
    225.                     if (b < 0) {  
    226.                         break;  // we reached EOF  
    227.                     } else {  
    228.                         bytesSkipped = 1; // we read one byte  
    229.                     }  
    230.                 }  
    231.                 totalBytesSkipped += bytesSkipped;  
    232.             }  
    233.             return totalBytesSkipped;  
    234.         }  
    235.     }  
    236.   
    237.     /** 
    238.      * The actual AsyncTask that will asynchronously download the image. 
    239.      */  
    240.     class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {  
    241.         private String url;  
    242.         private final WeakReference<ImageView> imageViewReference;  
    243.   
    244.         public BitmapDownloaderTask(ImageView imageView) {  
    245.             imageViewReference = new WeakReference<ImageView>(imageView);  
    246.         }  
    247.   
    248.         /** 
    249.          * Actual download method. 
    250.          */  
    251.         @Override  
    252.         protected Bitmap doInBackground(String... params) {  
    253.             url = params[0];  
    254.             return downloadBitmap(url);  
    255.         }  
    256.   
    257.         /** 
    258.          * Once the image is downloaded, associates it to the imageView 
    259.          */  
    260.         @Override  
    261.         protected void onPostExecute(Bitmap bitmap) {  
    262.             if (isCancelled()) {  
    263.                 bitmap = null;  
    264.             }  
    265.   
    266.             addBitmapToCache(url, bitmap);  
    267.   
    268.             if (imageViewReference != null) {  
    269.                 ImageView imageView = imageViewReference.get();  
    270.                 BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);  
    271.                 // Change bitmap only if this process is still associated with it  
    272.                 // Or if we don't use any bitmap to task association (NO_DOWNLOADED_DRAWABLE mode)  
    273.                 if ((this == bitmapDownloaderTask) || (mode != Mode.CORRECT)) {  
    274.                     imageView.setImageBitmap(bitmap);  
    275.                 }  
    276.             }  
    277.         }  
    278.     }  
    279.   
    280.   
    281.     /** 
    282.      * A fake Drawable that will be attached to the imageView while the download is in progress. 
    283.      * 
    284.      * <p>Contains a reference to the actual download task, so that a download task can be stopped 
    285.      * if a new binding is required, and makes sure that only the last started download process can 
    286.      * bind its result, independently of the download finish order.</p> 
    287.      */  
    288.     static class DownloadedDrawable extends ColorDrawable {  
    289.         private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;  
    290.   
    291.         public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {  
    292.             super(Color.BLACK);  
    293.             bitmapDownloaderTaskReference =  
    294.                 new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);  
    295.         }  
    296.   
    297.         public BitmapDownloaderTask getBitmapDownloaderTask() {  
    298.             return bitmapDownloaderTaskReference.get();  
    299.         }  
    300.     }  
    301.   
    302.     public void setMode(Mode mode) {  
    303.         this.mode = mode;  
    304.         clearCache();  
    305.     }  
    306.   
    307.       
    308.     /* 
    309.      * Cache-related fields and methods. 
    310.      *  
    311.      * We use a hard and a soft cache. A soft reference cache is too aggressively cleared by the 
    312.      * Garbage Collector. 
    313.      */  
    314.       
    315.     private static final int HARD_CACHE_CAPACITY = 10;  
    316.     private static final int DELAY_BEFORE_PURGE = 10 * 1000; // in milliseconds  
    317.   
    318.     // Hard cache, with a fixed maximum capacity and a life duration  
    319.     private final HashMap<String, Bitmap> sHardBitmapCache =  
    320.         new LinkedHashMap<String, Bitmap>(HARD_CACHE_CAPACITY / 2, 0.75f, true) {  
    321.         @Override  
    322.         protected boolean removeEldestEntry(LinkedHashMap.Entry<String, Bitmap> eldest) {  
    323.             if (size() > HARD_CACHE_CAPACITY) {  
    324.                 // Entries push-out of hard reference cache are transferred to soft reference cache  
    325.                 sSoftBitmapCache.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue()));  
    326.                 return true;  
    327.             } else  
    328.                 return false;  
    329.         }  
    330.     };  
    331.   
    332.     // Soft cache for bitmaps kicked out of hard cache  
    333.     private final static ConcurrentHashMap<String, SoftReference<Bitmap>> sSoftBitmapCache =  
    334.         new ConcurrentHashMap<String, SoftReference<Bitmap>>(HARD_CACHE_CAPACITY / 2);  
    335.   
    336.     private final Handler purgeHandler = new Handler();  
    337.   
    338.     private final Runnable purger = new Runnable() {  
    339.         public void run() {  
    340.             clearCache();  
    341.         }  
    342.     };  
    343.   
    344.     /** 
    345.      * Adds this bitmap to the cache. 
    346.      * @param bitmap The newly downloaded bitmap. 
    347.      */  
    348.     private void addBitmapToCache(String url, Bitmap bitmap) {  
    349.         if (bitmap != null) {  
    350.             synchronized (sHardBitmapCache) {  
    351.                 sHardBitmapCache.put(url, bitmap);  
    352.             }  
    353.         }  
    354.     }  
    355.   
    356.     /** 
    357.      * @param url The URL of the image that will be retrieved from the cache. 
    358.      * @return The cached bitmap or null if it was not found. 
    359.      */  
    360.     private Bitmap getBitmapFromCache(String url) {  
    361.         // First try the hard reference cache  
    362.         synchronized (sHardBitmapCache) {  
    363.             final Bitmap bitmap = sHardBitmapCache.get(url);  
    364.             if (bitmap != null) {  
    365.                 // Bitmap found in hard cache  
    366.                 // Move element to first position, so that it is removed last  
    367.                 sHardBitmapCache.remove(url);  
    368.                 sHardBitmapCache.put(url, bitmap);  
    369.                 return bitmap;  
    370.             }  
    371.         }  
    372.   
    373.         // Then try the soft reference cache  
    374.         SoftReference<Bitmap> bitmapReference = sSoftBitmapCache.get(url);  
    375.         if (bitmapReference != null) {  
    376.             final Bitmap bitmap = bitmapReference.get();  
    377.             if (bitmap != null) {  
    378.                 // Bitmap found in soft cache  
    379.                 return bitmap;  
    380.             } else {  
    381.                 // Soft reference has been Garbage Collected  
    382.                 sSoftBitmapCache.remove(url);  
    383.             }  
    384.         }  
    385.   
    386.         return null;  
    387.     }  
    388.    
    389.     /** 
    390.      * Clears the image cache used internally to improve performance. Note that for memory 
    391.      * efficiency reasons, the cache will automatically be cleared after a certain inactivity delay. 
    392.      */  
    393.     public void clearCache() {  
    394.         sHardBitmapCache.clear();  
    395.         sSoftBitmapCache.clear();  
    396.     }  
    397.   
    398.     /** 
    399.      * Allow a new delay before the automatic cache clear is done. 
    400.      */  
    401.     private void resetPurgeTimer() {  
    402.         purgeHandler.removeCallbacks(purger);  
    403.         purgeHandler.postDelayed(purger, DELAY_BEFORE_PURGE);  
    404.     }  
    405. }  



    里面有一些图片加载的方式方法,都很可取,不过对于ListView的优化而言,还应配合列表滚动监听来写。也就是说,当列表停止滚动,手离开屏幕的时候,再加载大数据,例如图片。稍后,我也会整理一篇,给大家提供参考借鉴。


    源代码来自:http://code.google.com/p/android-imagedownloader/

    滚动加载的例子:http://www.iteye.com/topic/1118828

    摘自:http://blog.csdn.net/xyz_fly/article/details/7864076

  • 相关阅读:
    Oracle资源管理器介绍(一)
    Pfile VS Spfile (MOS Note 249664.1)
    shell不能执行su 后的脚本
    Oracle 11g 新特性之Highly Available IP(HAIP)
    Oracle 11g新特性延迟段创建和truncate的增强
    Oracle 11g RAC停止和启动步骤
    测试Oracle 11gr2 RAC 非归档模式下,offline drop数据文件后的数据库的停止与启动测试全过程
    3.OGG函数
    4.3 高级特性(3) -- 过滤
    4.2 高级特性(2) -加密
  • 原文地址:https://www.cnblogs.com/veins/p/3897892.html
Copyright © 2011-2022 走看看