異步下載圖片+圖片緩存

功能如下:


e24a166c-55fa-3eaa-8eba-2a62fed9f4b9.jpg


流程如下:


bd352f84-70ce-33ee-b1c9-0eae9dec896d.jpg







  RemoteImageViewActivity:


Java代碼 收藏代碼
  1. publicclass RemoteImageViewActivity extends Activity {  

  2. /** Called when the activity is first created. */

  3. @Override

  4. publicvoid onCreate(Bundle savedInstanceState) {  

  5. super.onCreate(savedInstanceState);  

  6.        setContentView(R.layout.main);  

  7.        RemoteImageView img = (RemoteImageView) findViewById(R.id.remote_img);  

  8.        img.setDefaultImage(R.drawable.ic_launcher);  

  9.        img.setImageUrl("http://img2.kwcdn.kuwo.cn:81/star/albumcover/120/7/8/83787_1323997225.jpg");  

  10.    }  

  11. @Override

  12. protectedvoid onPause() {  

  13. // TODO Auto-generated method stub

  14. super.onPause();  

  15.    }  

  16. }  



ImageCache:


Java代碼 收藏代碼
  1. publicclass ImageCache extends WeakHashMap<String, Bitmap>{  

  2. /**

  3.     * 判斷該url是否存在

  4.     * @param url

  5.     * @return

  6.     */

  7. publicboolean isCached(String url){  

  8. return containsKey(url) && get(url) != null;  

  9.    }  

  10. }  



  RemoteImageApplication:


Java代碼 收藏代碼
  1. publicclass RemoteImageApplication extends Application {  

  2. publicstaticfinal String TAG = "RemoteImageApplication";  

  3. privatestatic RemoteImageApplication application;  

  4. private ImageCache mImageCache;  

  5. public SharedPreferences prefs = null;  

  6. publicstatic RemoteImageApplication getInstance() {  

  7. return application;  

  8.    }  

  9. @Override

  10. publicvoid onCreate() {  

  11. // TODO Auto-generated method stub

  12. super.onCreate();  

  13.        application = this;  

  14.        mImageCache = new ImageCache();  

  15.        prefs = PreferenceManager.getDefaultSharedPreferences(this);  

  16.    }  

  17. public ImageCache getImageCache() {  

  18. return mImageCache;  

  19.    }  

  20. }  



RemoteSettings:


Java代碼 收藏代碼
  1. publicclass RemoteSettings {  

  2. publicstaticfinal String CACHE_SIZE = "cache_size";  //圖片緩存保留大小,如果超過該大小,即進行自動清除緩存.

  3. }  


RemoteImageView:


Java代碼 收藏代碼
  1. publicclass RemoteImageView extends ImageView {  

  2. private Context mContext;  

  3. privatestaticint mCacheSize = 150; // 設置的緩存大小。

  4. privatestaticfinalint MAX_FAILURES = 3; // 下載的嘗試請求次數

  5. privateint mFailure; // 下載失敗次數

  6. private String mUrl; // 當前下載的url

  7. private String mCurrentlyGrabbedUrl; // 當前下載成功的url

  8. privatefinalstatic String JAMENDO_DIR = "Android/data/com.teleca.jamendo"; // 文件緩存存放的路徑.

  9. privatefinalstaticlong MB = 1073741824;  

  10. public RemoteImageView(Context context, AttributeSet attrs, int defStyle) {  

  11. super(context, attrs, defStyle);  

  12.        mContext = context;  

  13.    }  

  14. public RemoteImageView(Context context, AttributeSet attrs) {  

  15. super(context, attrs);  

  16.        mContext = context;  

  17.    }  

  18. public RemoteImageView(Context context) {  

  19. super(context);  

  20.        mContext = context;  

  21.    }  

  22. /**

  23.     * 設置默認圖片

  24.     */

  25. publicvoid setDefaultImage(Integer resid) {  

  26.        setImageResource(resid);  

  27.    }  

  28. /**

  29.     * 設置需要異步加載的圖片

  30.     */

  31. publicvoid setImageUrl(String url) {  

  32. // 下載失敗進行重試,如果重試次數超過規定的限制,則直接返回.

  33. if (mUrl != null

  34.                && mUrl.equals(url)  

  35.                && (mCurrentlyGrabbedUrl == null || (mCurrentlyGrabbedUrl != null && !mCurrentlyGrabbedUrl  

  36.                        .equals(url)))) {  

  37.            mFailure++;  

  38. if (mFailure > MAX_FAILURES) {  

  39.                Log.e(RemoteImageApplication.TAG, "下載該圖片地址失敗:" + url);  

  40. return;  

  41.            }  

  42.        } else {  

  43.            mUrl = url;  

  44.            mFailure = 0;  

  45.        }  

  46.        ImageCache imageCache = RemoteImageApplication.getInstance()  

  47.                .getImageCache();  

  48. if (imageCache.isCached(url)) {  

  49.            setImageBitmap(imageCache.get(url));  

  50.        } else {  

  51. // 如果內存中沒有該緩存,則從文件中進行查找.

  52.            String fileName = convertUrlToFileName(url); // 進行文件名處理

  53.            String filepath = getDirectory(fileName); // 取得緩存文件夾目錄

  54.            String pathFileName = filepath + "/" + fileName; // 組拼文件

  55.            File pathFile = new File(pathFileName);  

  56. if (!pathFile.exists()) {  

  57. try {  

  58.                    pathFile.createNewFile();  

  59.                } catch (IOException e) {  

  60.                    Log.d(RemoteImageApplication.TAG, "創建圖片文件失敗:"

  61.                            + pathFileName);  

  62.                }  

  63.            }  

  64.            Bitmap tbmp = BitmapFactory.decodeFile(pathFileName);  

  65. if (tbmp == null) {  

  66.                Log.d(RemoteImageApplication.TAG, "圖片文件不存在,開始進行下載");  

  67. try {  

  68. new DownloadTask().execute(url);  

  69.                } catch (RejectedExecutionException e) {  

  70.                    Log.d(RemoteImageApplication.TAG, "下載失敗");  

  71.                }  

  72.            } else {  

  73.                Log.i(RemoteImageApplication.TAG, "從文件中加載圖片");  

  74.                RemoteImageApplication.getInstance().getImageCache()  

  75.                        .put(url, tbmp);  

  76. this.setImageBitmap(tbmp);  

  77.            }  

  78.            updateCacheSize(pathFileName); // 進行檢測文件大小,以便於清除緩存.

  79.        }  

  80.    }  

  81. privatevoid updateCacheSize(String pathFileName) {  

  82. // TODO Auto-generated method stub

  83.        updateSizeCache(pathFileName);  

  84.    }  

  85. /**

  86.     * 檢查文件目錄是否超過規定的緩存大小

  87.     *

  88.     * @param fileName

  89.     */

  90. privatevoid updateSizeCache(String pathFileName) {  

  91. // TODO Auto-generated method stub

  92.        mCacheSize = PreferenceManager.getDefaultSharedPreferences(mContext)  

  93.                .getInt(RemoteSettings.CACHE_SIZE, 100); // 讀取設置的緩存大小,前臺可以動態設置此值

  94. if (isSDCardEnable()) {  

  95.            String extStorageDirectory = Environment  

  96.                    .getExternalStorageDirectory().toString(); // 取得SD根路徑

  97.            String dirPath = extStorageDirectory + "/" + JAMENDO_DIR  

  98.                    + "/imagecache";  

  99.            File dirFile = new File(dirPath);  

  100.            File[] files = dirFile.listFiles();  

  101. long dirSize = 0;  

  102. for (File file : files) {  

  103.                dirSize += file.length();  

  104.            }  

  105. if (dirSize > mCacheSize * MB) {  

  106.                clearCache();  

  107.            }  

  108.        }  

  109.    }  

  110. /**

  111.     * 異步下載圖片

  112.     *

  113.     * @ClassName: DownloadTask

  114.     * @author 姜濤

  115.     * @version 1.0 2012-1-15 下午5:06:21

  116.     */

  117. class DownloadTask extends AsyncTask<String, Void, String> {  

  118. private String mTaskUrl;  

  119. private Bitmap mBmp = null;  

  120. @Override

  121. publicvoid onPreExecute() {  

  122. // loadDefaultImage();

  123. super.onPreExecute();  

  124.        }  

  125. @Override

  126. public String doInBackground(String... params) {  

  127.            mTaskUrl = params[0];  

  128.            InputStream stream = null;  

  129.            URL imageUrl;  

  130.            Bitmap bmp = null;  

  131. try {  

  132.                imageUrl = new URL(mTaskUrl);  

  133. try {  

  134.                    stream = imageUrl.openStream();  

  135.                    bmp = BitmapFactory.decodeStream(stream);  

  136. try {  

  137. if (bmp != null) {  

  138.                            mBmp = bmp;  

  139.                            RemoteImageApplication.getInstance()  

  140.                                    .getImageCache().put(mTaskUrl, bmp);  

  141.                            Log.d(RemoteImageApplication.TAG,  

  142. "圖片緩存到application中: " + mTaskUrl);  

  143.                        }  

  144.                    } catch (NullPointerException e) {  

  145.                        Log.w(RemoteImageApplication.TAG, "下載失敗,圖片爲空:"

  146.                                + mTaskUrl);  

  147.                    }  

  148.                } catch (IOException e) {  

  149.                    Log.w(RemoteImageApplication.TAG, "無法加載該url:" + mTaskUrl);  

  150.                } finally {  

  151. try {  

  152. if (stream != null) {  

  153.                            stream.close();  

  154.                        }  

  155.                    } catch (IOException e) {  

  156.                    }  

  157.                }  

  158.            } catch (MalformedURLException e) {  

  159.                e.printStackTrace();  

  160.            }  

  161. return mTaskUrl;  

  162.        }  

  163. @Override

  164. publicvoid onPostExecute(String url) {  

  165. super.onPostExecute(url);  

  166.            Bitmap bmp = RemoteImageApplication.getInstance().getImageCache()  

  167.                    .get(url);  

  168. if (bmp == null) {  

  169.                Log.w(RemoteImageApplication.TAG, "嘗試重新下載:" + url);  

  170.                RemoteImageView.this.setImageUrl(url);  

  171.            } else {  

  172.                RemoteImageView.this.setImageBitmap(bmp);  

  173.                mCurrentlyGrabbedUrl = url;  

  174.                saveBmpToSd(mBmp, url);  

  175.            }  

  176.        }  

  177.    };  

  178. /**

  179.     * 把圖片保存到本地

  180.     *

  181.     * @param bm

  182.     * @param url

  183.     */

  184. privatevoid saveBmpToSd(Bitmap bm, String url) {  

  185. if (bm == null) {  

  186. return;  

  187.        }  

  188. if (mCacheSize == 0) {  

  189. return;  

  190.        }  

  191.        String filename = convertUrlToFileName(url);  

  192.        String dir = getDirectory(filename);  

  193.        File file = new File(dir + "/" + filename);  

  194. try {  

  195.            file.createNewFile();  

  196.            OutputStream outStream = new FileOutputStream(file);  

  197.            bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);  

  198.            outStream.flush();  

  199.            outStream.close();  

  200.            Log.i(RemoteImageApplication.TAG, "圖片已保存到sd卡");  

  201.        } catch (FileNotFoundException e) {  

  202.            Log.w(RemoteImageApplication.TAG, "無法找到文件目錄");  

  203.        } catch (IOException e) {  

  204.            Log.w(RemoteImageApplication.TAG, "操作文件出錯");  

  205.        }  

  206.    }  

  207. /**

  208.     * 組拼文件名,後綴名用dat代替,避免別人使用圖片管理器搜索出這種對於她們無用的圖片.

  209.     *

  210.     * @param url

  211.     * @return

  212.     */

  213. private String convertUrlToFileName(String url) {  

  214.        String filename = url;  

  215.        filename = filename.replace("http://", "");  

  216.        filename = filename.replace("/", ".");  

  217.        filename = filename.replace(":", ".");  

  218.        filename = filename.replace("jpg", "dat");  

  219.        filename = filename.replace("png", "dat");  

  220. return filename;  

  221.    }  

  222. /**

  223.     * 返回緩存圖片所存放的文件夾

  224.     *

  225.     * @param filename

  226.     * @return

  227.     */

  228. private String getDirectory(String filename) {  

  229.        String extStorageDirectory = Environment.getExternalStorageDirectory()  

  230.                .toString(); // 取得SD根路徑

  231.        String dirPath = extStorageDirectory + "/" + JAMENDO_DIR  

  232.                + "/imagecache";  

  233.        File dirFile = new File(dirPath);  

  234. if (!dirFile.exists()) {  

  235.            dirFile.mkdirs();  

  236.        }  

  237. return dirPath;  

  238.    }  

  239. /**

  240.     * 清除緩存

  241.     */

  242. privatevoid clearCache() {  

  243. if (isSDCardEnable()) {  

  244.            String extStorageDirectory = Environment  

  245.                    .getExternalStorageDirectory().toString(); // 取得SD根路徑

  246.            String dirPath = extStorageDirectory + "/" + JAMENDO_DIR  

  247.                    + "/imagecache";  

  248.            File dir = new File(dirPath);  

  249.            File[] files = dir.listFiles(); // 取得該目錄下的所有文件

  250. if (files == null || files.length == 0) {  

  251. return;  

  252.            }  

  253. for (File file : files) {  

  254.                file.delete();  

  255.            }  

  256.            Log.d(RemoteImageApplication.TAG, "已清除緩存:" + dirPath);  

  257.        }  

  258.    }  

  259. /**

  260.     * 判斷SD卡是否可用

  261.     */

  262. publicstaticboolean isSDCardEnable() {  

  263. return Environment.getExternalStorageState().equals(  

  264.                Environment.MEDIA_MOUNTED);  

  265.    }  

  266. }  

本文轉自:http://lewisliu.iteye.com/blog/1346820

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章