Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> 實戰Android仿人人客戶端之對從服務器端(網絡)獲取的圖片進行本地雙緩存處理的編碼實現

實戰Android仿人人客戶端之對從服務器端(網絡)獲取的圖片進行本地雙緩存處理的編碼實現

編輯:Android開發實例

       這篇是基於上一篇 實戰Android仿人人客戶端之對從服務器端(網絡)獲取的圖片進行本地進行雙緩存處理的業務流程圖 來進行講解,沒看過的可以先閱讀下上一篇博文,其實我個人覺得圖片雙緩存處理這塊,一張流程圖已足以說明一切。至於編碼實現,不同的人有不同的實現方式,下面我就和大家聊一聊我的實現方式:

一、圖片雙緩存處理,類圖如下:

二、網絡圖片本地雙緩存的編碼實現(以獲取用戶圖像為例):

       1、發出需要顯示用戶圖像的請求

  1. String headUrl = user.getHeadurl();  
  2. LogUtil.i(TAG, "headUrl = " + user.getHeadurl());  
  3.  
  4. // 用戶圖像的大小48x48,單位為dip,轉換為px  
  5. int widthPx = DensityUtil.dip2px(mContext, 48);  
  6.  
  7. // 要一張圓角高質量的圖片  
  8. ImageInfo imgInfo = new ImageInfo(mLeftPanelLayout.ivUserIcon, headUrl, widthPx, widthPx, true, false);  
  9. mImageLoader.displayImage(imgInfo);  

        注:mLeftPanelLayout.ivUserIcon為ImageView;ImageInfo對象封裝了圖片請求參數。

        2、根據URL從內存緩存中獲取Bitmap對象,找到了Bitmap對象,用ImageView對象顯示圖像,到這裡終止。

  1. Bitmap bitmap = memoryCache.get(url);  
  2. if (bitmap != null) {  
  3.     imageView.setImageBitmap(bitmap);  
  4. }  

           注:memoryCache是MemoryCache(內存緩存類)的對象引用。

        3 、沒有從緩存中找到了Bitmap對象,則根據URL從文件緩存中獲取File對象,將File對象解碼(解析)成Bitmap對象,用ImageView對象顯示用戶圖像,到這裡終止。

  1. final File file = fileCache.getFile(url);  
  2. if(file.exists()){  
  3.     String pathName = file.getAbsolutePath();  
  4.     System.out.println("pathName = " + pathName);  
  5.     System.out.println("file.length() = " + file.length());  
  6.       
  7.     bitmap = BitmapFactory.decodeFile(pathName);  
  8.     imageView.setImageBitmap(bitmap);  
  9. }  

           注:fileCache為文件緩存類的引用             

        4、沒有從文件緩存中找到File對象,則開啟網絡請求業務線程。

  1. // 開啟線程加載圖片  
  2.  try {  
  3.      AsyncBaseRequest asyncRequest = new AsyncHttpGet(url, null, null, new ResultCallback() {  
  4.  
  5.          @Override 
  6.          public void onSuccess(Object obj) {  
  7.                
  8.          }  
  9.  
  10.          @Override 
  11.          public void onFail(int errorCode) {  
  12.              System.out.println("Loading image error. errorCode = " + errorCode);  
  13.          }  
  14.      });  
  15.  
  16.      mDefaultThreadPool.execute(asyncRequest);  
  17.      mAsyncRequests.add(asyncRequest);  
  18.  } catch (IOException e) {  
  19.      e.printStackTrace();  
  20.  }  

         5、網絡請求返回的圖片數據流可能會很大,直接解碼生成Bitmap對象,可能會造成OOM。因此,要根據指定的壓縮比例,獲得合適的Bitmap

  1. Bitmap bitmap = BitmapUtil.decodeStream((InputStream) obj, imgInfo.getWidth(), imgInfo.getHeight()); 

        6、上一步處理過後,可能解碼生成的Bitmap對象還會很大,可能還會造成OOM,因此,對Bitmap對象再次進行質量壓縮。

  1. if (imgInfo.isCompress()) {  
  2.     // 對Bitmap進行質量壓縮  
  3.     bitmap = BitmapUtil.compressBitmap(bitmap);  

      7、進行本地文件緩存

  1. try {  
  2.     fileCache.writeToFile(inStream, file);  
  3. } catch (IOException e) {  
  4.     // TODO Auto-generated catch block  
  5.     e.printStackTrace();  

      8、進行本地內存緩存

  1. // 將數據流將其轉換成Bitmap  
  2. bitmap = BitmapFactory.decodeStream(inStream);  
  3.  
  4. // 存入內存緩存中  
  5. memoryCache.put(url, bitmap); 

      9、用ImageView對象顯示用戶圖像,到這裡終止。

  1. // 用ImageView對象顯示圖片  
  2. final Bitmap btm = bitmap;  
  3. mHandler.post(new Runnable() {  
  4.  
  5.     @Override 
  6.     public void run() {  
  7.         imageView.setImageBitmap(btm);  
  8.     }  
  9. }); 

       加載圖片的完整方法,代碼如下:

  1. /**  
  2.  * 加載圖片  
  3.  * @param imgInfo 圖片信息  
  4.  */ 
  5. public void displayImage(final ImageInfo imgInfo) {  
  6.     final ImageView imageView = imgInfo.getImageView();  
  7.     final String url = imgInfo.getUrl();  
  8.  
  9.     imageViews.put(imageView, url);  
  10.  
  11.     // 從內存緩存中查找  
  12.     Bitmap bitmap = memoryCache.get(url);  
  13.     if (bitmap != null) {  
  14.         imageView.setImageBitmap(bitmap);  
  15.     } else {  
  16.         // 從文件緩存中查找  
  17.         final File file = fileCache.getFile(url);  
  18.         if (file.exists()) {  
  19.             String pathName = file.getAbsolutePath();  
  20.             System.out.println("pathName = " + pathName);  
  21.             System.out.println("file.length() = " + file.length());  
  22.  
  23.             bitmap = BitmapFactory.decodeFile(pathName);  
  24.             imageView.setImageBitmap(bitmap);  
  25.         } else {  
  26.             // 開啟線程加載圖片  
  27.             try {  
  28.                 AsyncBaseRequest asyncRequest = new AsyncHttpGet(url, null, null, new ResultCallback() {  
  29.  
  30.                     @Override 
  31.                     public void onSuccess(Object obj) {  
  32.                         if (obj == null || !(obj instanceof InputStream)) {  
  33.                             System.out.println("Loading image return Object is null or not is InputStream.");  
  34.                             return;  
  35.                         }  
  36.  
  37.                         try {  
  38.                             // 根據指定的壓縮比例,獲得合適的Bitmap  
  39.                             Bitmap bitmap = BitmapUtil.decodeStream((InputStream) obj, imgInfo.getWidth(), imgInfo.getHeight());  
  40.                               
  41.                             if (imgInfo.isRounded()) {  
  42.                                  // 將圖片變成圓角  
  43.                                  // bitmap = BitmapUtil.drawRoundCorner(bitmap, 8);  
  44.                                  bitmap = BitmapUtil.drawRoundBitmap(bitmap, 8);  
  45.                             }  
  46.                               
  47.                             if (imgInfo.isCompress()) {  
  48.                                 // 對Bitmap進行質量壓縮  
  49.                                 bitmap = BitmapUtil.compressBitmap(bitmap);  
  50.                             }  
  51.                               
  52.                             // 將Bitmap轉換成ByteArrayInputStream  
  53.                             ByteArrayOutputStream outStream = new ByteArrayOutputStream();  
  54.                             bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);  
  55.                             ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());  
  56.                               
  57.                             // 將進行質量壓縮後的數據寫入文件(文件緩存)  
  58.                             fileCache.writeToFile(inStream, file);  
  59.                               
  60.                             // 存入內存緩存中  
  61.                             memoryCache.put(url, bitmap);  
  62.  
  63.                             // 防止圖片錯位  
  64.                             String tag = imageViews.get(imageView);  
  65.                             if (tag == null || !tag.equals(url)) {  
  66.                                 System.out.println("tag is null or url and ImageView disaccord.");  
  67.                                 return;  
  68.                             }  
  69.                               
  70.                             // 用ImageView對象顯示圖片  
  71.                             final Bitmap btm = bitmap;  
  72.                             mHandler.post(new Runnable() {  
  73.  
  74.                                 @Override 
  75.                                 public void run() {  
  76.                                     imageView.setImageBitmap(btm);  
  77.                                 }  
  78.                             });  
  79.                               
  80.                               
  81.                         } catch (IOException e) {  
  82.                             // 這裡不做處理,因為默認顯示的圖片在xml組件配置裡已設置  
  83.                             e.printStackTrace();  
  84.                         }  
  85.                           
  86.                     }  
  87.  
  88.                     @Override 
  89.                     public void onFail(int errorCode) {  
  90.                         System.out.println("Loading image error. errorCode = " + errorCode);  
  91.                     }  
  92.                 });  
  93.  
  94.                 mDefaultThreadPool.execute(asyncRequest);  
  95.                 mAsyncRequests.add(asyncRequest);  
  96.             } catch (IOException e) {  
  97.                 e.printStackTrace();  
  98.             }  
  99.         }  
  100.     }  
  101. }  

      三、在上述業務處理過程中,遇到的問題及解決思路(記錄處理過程)

       1、根據指定的壓縮比例,獲得合適的Bitmap,閱讀如下代碼:

  1. /**  
  2.  * 根據指定的壓縮比例,獲得合適的Bitmap  
  3.  * @param inStream InputStream  
  4.  * @param width 指定的寬度  
  5.  * @param height 指定的高度  
  6.  */ 
  7. public static Bitmap decodeStream(InputStream inStream, int width, int height) {  
  8.     BitmapFactory.Options options = new BitmapFactory.Options();  
  9.     options.inJustDecodeBounds = true;  
  10.     BitmapFactory.decodeStream(inStream, null, options);  
  11.  
  12.     int w = options.outWidth;  
  13.     int h = options.outHeight;  
  14.  
  15.     // 從服務器端獲取的圖片大小為:80x120  
  16.     // 我們想要的圖片大小為:40x40  
  17.     // 縮放比:120/40 = 3,也就是說我們要的圖片大小為原圖的1/3  
  18.  
  19.     // 縮放比。由於是固定比例縮放,只用高或者寬其中一個數據進行計算即可  
  20.     int ratio = 1; // 默認為不縮放  
  21.     if (w >= h && w > width) {  
  22.         ratio = (int) (w / width);  
  23.     } else if (w < h && h > height) {  
  24.         ratio = (int) (h / height);  
  25.     }  
  26.  
  27.     if (ratio <= 0) {  
  28.         ratio = 1;  
  29.     }  
  30.  
  31.     System.out.println("圖片的縮放比例值ratio = " + ratio);  
  32.  
  33.     options.inJustDecodeBounds = false;  
  34.     // 屬性值inSampleSize表示縮略圖大小為原始圖片大小的幾分之一,即如果這個值為2,  
  35.     // 則取出的縮略圖的寬和高都是原始圖片的1/2,圖片大小就為原始大小的1/4。  
  36.     options.inSampleSize = ratio;  
  37.  
  38.     return BitmapFactory.decodeStream(inStream, null, options);  
  39. }  

       注:inStream為從網絡獲取後,直接傳進來的。

       運行上面的後,返回的Bitmap對象為null。究其原因,在設置 options.inJustDecodeBounds = true後,我們調用了BitmapFactory.decodeStream(inStream, null, options)方法獲取圖片的大小,但是該方法在執行完後,應該在內部把傳進去的InputStream關閉掉了。第二次的時候就讀不到數據了。解決思路,將從網絡獲取到的數據流先保存起來。解決方法一:

  1. /**  
  2.    * 根據指定的壓縮比例,獲得合適的Bitmap(方法一)  
  3.    * @param file File  
  4.    * @param width 指定的寬度  
  5.    * @param height 指定的高度  
  6.    * @return Bitmap  
  7.    */ 
  8.   public static Bitmap decodeStream(File file, int width, int height) {  
  9.       BitmapFactory.Options options = new BitmapFactory.Options();  
  10.       options.inJustDecodeBounds = true;  
  11.       BitmapFactory.decodeFile(file.getAbsolutePath(), options);  
  12.  
  13.       int w = options.outWidth;  
  14.       int h = options.outHeight;  
  15.  
  16.       // 從服務器端獲取的圖片大小為:80x120  
  17.       // 我們想要的圖片大小為:40x40  
  18.       // 縮放比:120/40 = 3,也就是說我們要的圖片大小為原圖的1/3  
  19.  
  20.       // 縮放比。由於是固定比例縮放,只用高或者寬其中一個數據進行計算即可  
  21.       int ratio = 1; // 默認為不縮放  
  22.       if (w >= h && w > width) {  
  23.           ratio = (int) (w / width);  
  24.       } else if (w < h && h > height) {  
  25.           ratio = (int) (h / height);  
  26.       }  
  27.  
  28.       if (ratio <= 0) {  
  29.           ratio = 1;  
  30.       }  
  31.  
  32.       System.out.println("圖片的縮放比例值ratio = " + ratio);  
  33.  
  34.       options = new BitmapFactory.Options();  
  35.       options.inJustDecodeBounds = false;  
  36.       // 屬性值inSampleSize表示縮略圖大小為原始圖片大小的幾分之一,即如果這個值為2,  
  37.       // 則取出的縮略圖的寬和高都是原始圖片的1/2,圖片大小就為原始大小的1/4。  
  38.       options.inSampleSize = ratio;  
  39.  
  40.       return BitmapFactory.decodeFile(file.getAbsolutePath(), options);  
  41.   }  

解決方法二:

  1. /**  
  2.    * 根據指定的壓縮比例,獲得合適的Bitmap(方法二)  
  3.    * @param inStream InputStream  
  4.    * @param width 指定的寬度  
  5.    * @param height 指定的高度  
  6.    * @return Bitmap  
  7.    * @throws IOException  
  8.    */ 
  9.   public static Bitmap decodeStream(InputStream inStream, int width, int height) throws IOException {  
  10.       BitmapFactory.Options options = new BitmapFactory.Options();  
  11.       options.inJustDecodeBounds = true;  
  12.  
  13.       // 從輸入流讀取數據  
  14.       byte[] data = StreamTool.read(inStream);  
  15.       BitmapFactory.decodeByteArray(data, 0, data.length, options);  
  16.  
  17.       int w = options.outWidth;  
  18.       int h = options.outHeight;  
  19.  
  20.       // 從服務器端獲取的圖片大小為:80x120  
  21.       // 我們想要的圖片大小為:40x40  
  22.       // 縮放比:120/40 = 3,也就是說我們要的圖片大小為原圖的1/3  
  23.  
  24.       // 縮放比。由於是固定比例縮放,只用高或者寬其中一個數據進行計算即可  
  25.       int ratio = 1; // 默認為不縮放  
  26.       if (w >= h && w > width) {  
  27.           ratio = (int) (w / width);  
  28.       } else if (w < h && h > height) {  
  29.           ratio = (int) (h / height);  
  30.       }  
  31.  
  32.       if (ratio <= 0) {  
  33.           ratio = 1;  
  34.       }  
  35.  
  36.       System.out.println("圖片的縮放比例值ratio = " + ratio);  
  37.  
  38.       options.inJustDecodeBounds = false;  
  39.       // 屬性值inSampleSize表示縮略圖大小為原始圖片大小的幾分之一,即如果這個值為2,  
  40.       // 則取出的縮略圖的寬和高都是原始圖片的1/2,圖片大小就為原始大小的1/4。  
  41.       options.inSampleSize = ratio;  
  42.       return BitmapFactory.decodeByteArray(data, 0, data.length);  
  43.   }  

解決方法三:從網絡返回的數據流中只讀取圖片的信息(寬度和高度),計算壓縮比例,之後再次從網絡讀取數據按第一次計算出的壓縮比例,獲得合適的Bitmap。(這個是下下策,要訪問兩次網絡)

       2、對Bitmap進行質量壓縮,閱讀如下代碼:

  1. /**  
  2.   * 對Bitmap進行質量壓縮  
  3.   * @param bitmap Bitmap  
  4.   * @return ByteArrayInputStream  
  5.   */ 
  6.  public static Bitmap compressBitmap(Bitmap bitmap) {  
  7.      ByteArrayOutputStream outStream = new ByteArrayOutputStream();  
  8.      // 圖片質量默認值為100,表示不壓縮  
  9.      int quality = 100;  
  10.      // PNG是無損的,將會忽略質量設置。因此,這裡設置為JPEG  
  11.      bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outStream);  
  12.  
  13.      // 判斷壓縮後圖片的大小是否大於100KB,大於則繼續壓縮  
  14.      while (outStream.toByteArray().length / 1024 > 100) {  
  15.          outStream.reset();  
  16.  
  17.          // 壓縮quality%,把壓縮後的數據存放到baos中  
  18.          bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outStream);  
  19.          quality -= 10;  
  20.      }  
  21.  
  22.      System.out.println("quality = " + quality);  
  23.  
  24.      byte[] data = outStream.toByteArray();  
  25.      return BitmapFactory.decodeByteArray(data, 0, data.length);  
  26.  }  

        注意:  bitmap.compress(Bitmap.CompressFormat.PNG, quality, outStream);如果這麼寫,是沒有壓縮效果的。因為PNG是無損的,將會忽略質量設置。

四、上述講解中涉及到的類,完整的源文件如下:

加載(裝載)圖片類

  1. package com.everyone.android.bitmap;  
  2.  
  3. import java.io.ByteArrayInputStream;  
  4. import java.io.ByteArrayOutputStream;  
  5. import java.io.File;  
  6. import java.io.IOException;  
  7. import java.io.InputStream;  
  8. import java.text.SimpleDateFormat;  
  9. import java.util.Collections;  
  10. import java.util.LinkedHashMap;  
  11. import java.util.List;  
  12. import java.util.Map;  
  13.  
  14. import android.graphics.Bitmap;  
  15. import android.graphics.BitmapFactory;  
  16. import android.os.Handler;  
  17. import android.widget.ImageView;  
  18.  
  19. import com.everyone.android.AppBaseActivity;  
  20. import com.everyone.android.callback.ResultCallback;  
  21. import com.everyone.android.entity.ImageInfo;  
  22. import com.everyone.android.net.AsyncBaseRequest;  
  23. import com.everyone.android.net.AsyncHttpGet;  
  24. import com.everyone.android.net.DefaultThreadPool;  
  25. import com.everyone.android.utils.BitmapUtil;  
  26.  
  27. /**  
  28.  * 功能描述:加載(裝載)圖片  
  29.  *   
  30.  * 在以前,一個非常流行的內存緩存的實現是使用SoftReference or WeakReference ,但是這種辦法現在並不推薦。  
  31.  * 從Android 2.3開始,垃圾回收器會更加積極的去回收軟引用和弱引用引用的對象,這樣導致這種做法相當的無效。  
  32.  * 另外,在Android 3.0之前,圖片數據保存在本地內存中,它們不是以一種可預見的方式來釋放的,  
  33.  * 這樣可能會導致應用內存的消耗量出現短暫的超限,應用程序崩潰 。  
  34.  *   
  35.  * @author android_ls  
  36.  */ 
  37. public class ImageLoader {  
  38.  
  39.     /**  
  40.      * 內存緩存  
  41.      */ 
  42.     private MemoryCache memoryCache;  
  43.  
  44.     /**  
  45.      * 文件緩存  
  46.      */ 
  47.     private FileCache fileCache;  
  48.  
  49.     /**  
  50.      * 存放圖片的顯示視圖ImageView和圖片的URL  
  51.      */ 
  52.     private Map<ImageView, String> imageViews = Collections.synchronizedMap(new LinkedHashMap<ImageView, String>());  
  53.  
  54.     private List<AsyncBaseRequest> mAsyncRequests;  
  55.  
  56.     private DefaultThreadPool mDefaultThreadPool;  
  57.  
  58.     private Handler mHandler;  
  59.  
  60.     public ImageLoader(AppBaseActivity activity) {  
  61.         this.memoryCache = new MemoryCache();  
  62.         this.fileCache = new FileCache(activity.getContext());  
  63.         this.mAsyncRequests = activity.getAsyncRequests();  
  64.         this.mDefaultThreadPool = activity.getDefaultThreadPool();  
  65.         this.mHandler = activity.getHandler();  
  66.     }  
  67.  
  68.     /**  
  69.      * 加載圖片  
  70.      * @param imgInfo 圖片信息  
  71.      */ 
  72.     public void displayImage(final ImageInfo imgInfo) {  
  73.         final ImageView imageView = imgInfo.getImageView();  
  74.         final String url = imgInfo.getUrl();  
  75.  
  76.         imageViews.put(imageView, url);  
  77.  
  78.         // 從內存緩存中查找  
  79.         Bitmap bitmap = memoryCache.get(url);  
  80.         if (bitmap != null) {  
  81.             imageView.setImageBitmap(bitmap);  
  82.         } else {  
  83.             // 從文件緩存中查找  
  84.             final File file = fileCache.getFile(url);  
  85.             if (file.exists()) {  
  86.                 String pathName = file.getAbsolutePath();  
  87.                 System.out.println("pathName = " + pathName);  
  88.                 System.out.println("file.length() = " + file.length());  
  89.  
  90.                 SimpleDateFormat mDateFormat = new SimpleDateFormat ("yyyy年MM月dd日 HH:mm:ss");  
  91.                 System.out.println("file.lastModified() = " + mDateFormat.format(file.lastModified()));  
  92.                   
  93.                 bitmap = BitmapFactory.decodeFile(pathName);  
  94.                 imageView.setImageBitmap(bitmap);  
  95.             } else {  
  96.                 // 開啟線程加載圖片  
  97.                 try {  
  98.                     AsyncBaseRequest asyncRequest = new AsyncHttpGet(url, null, null, new ResultCallback() {  
  99.  
  100.                         @Override 
  101.                         public void onSuccess(Object obj) {  
  102.                             if (obj == null || !(obj instanceof InputStream)) {  
  103.                                 System.out.println("Loading image return Object is null or not is InputStream.");  
  104.                                 return;  
  105.                             }  
  106.  
  107.                             try {  
  108.                                 // 根據指定的壓縮比例,獲得合適的Bitmap  
  109.                                 Bitmap bitmap = BitmapUtil.decodeStream((InputStream) obj, imgInfo.getWidth(), imgInfo.getHeight());  
  110.                                   
  111.                                 if (imgInfo.isRounded()) {  
  112.                                      // 將圖片變成圓角  
  113.                                      // bitmap = BitmapUtil.drawRoundCorner(bitmap, 8);  
  114.                                      bitmap = BitmapUtil.drawRoundBitmap(bitmap, 8);  
  115.                                 }  
  116.                                   
  117.                                 if (imgInfo.isCompress()) {  
  118.                                     // 對Bitmap進行質量壓縮  
  119.                                     bitmap = BitmapUtil.compressBitmap(bitmap);  
  120.                                 }  
  121.                                   
  122.                                 // 將Bitmap轉換成ByteArrayInputStream  
  123.                                 ByteArrayOutputStream outStream = new ByteArrayOutputStream();  
  124.                                 bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);  
  125.                                 ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());  
  126.                                   
  127.                                 // 將進行質量壓縮後的數據寫入文件(文件緩存)  
  128.                                 fileCache.writeToFile(inStream, file);  
  129.                                   
  130.                                 // 存入內存緩存中  
  131.                                 memoryCache.put(url, bitmap);  
  132.  
  133.                                 // 防止圖片錯位  
  134.                                 String tag = imageViews.get(imageView);  
  135.                                 if (tag == null || !tag.equals(url)) {  
  136.                                     System.out.println("tag is null or url and ImageView disaccord.");  
  137.                                     return;  
  138.                                 }  
  139.                                   
  140.                                 // 用ImageView對象顯示圖片  
  141.                                 final Bitmap btm = bitmap;  
  142.                                 mHandler.post(new Runnable() {  
  143.  
  144.                                     @Override 
  145.                                     public void run() {  
  146.                                         imageView.setImageBitmap(btm);  
  147.                                     }  
  148.                                 });  
  149.                                   
  150.                                   
  151.                             } catch (IOException e) {  
  152.                                 // 這裡不做處理,因為默認顯示的圖片在xml組件配置裡已設置  
  153.                                 e.printStackTrace();  
  154.                             }  
  155.                               
  156.                         }  
  157.  
  158.                         @Override 
  159.                         public void onFail(int errorCode) {  
  160.                             System.out.println("Loading image error. errorCode = " + errorCode);  
  161.                         }  
  162.                     });  
  163.  
  164.                     mDefaultThreadPool.execute(asyncRequest);  
  165.                     mAsyncRequests.add(asyncRequest);  
  166.                 } catch (IOException e) {  
  167.                     e.printStackTrace();  
  168.                 }  
  169.             }  
  170.         }  
  171.     }  
  172.  
  173. }  


內存緩存類

  1. package com.everyone.android.bitmap;  
  2.  
  3. import java.util.Collections;  
  4. import java.util.Iterator;  
  5. import java.util.LinkedHashMap;  
  6. import java.util.Map;  
  7. import java.util.Map.Entry;  
  8.  
  9. import android.graphics.Bitmap;  
  10. import android.util.Log;  
  11.  
  12. /**  
  13.  * 功能描述:內存緩存類  
  14.  *   
  15.  * @author android_ls  
  16.  */ 
  17. public class MemoryCache {  
  18.  
  19.     /**  
  20.      * 打印LOG的TAG  
  21.      */ 
  22.     private static final String TAG = "MemoryCache";  
  23.  
  24.     /**  
  25.      * 放入緩存時是個同步操作  
  26.      * LinkedHashMap構造方法的最後一個參數true代表這個map裡的元素將按照最近使用次數由少到多排列,  
  27.      * 這樣的好處是如果要將緩存中的元素替換,則先遍歷出最近最少使用的元素來替換以提高效率  
  28.      */ 
  29.     private Map<String, Bitmap> cacheMap = Collections.synchronizedMap(new LinkedHashMap<String, Bitmap>(10, 1.5f, true));  
  30.  
  31.     // 緩存只能占用的最大堆內存  
  32.     private long maxMemory;  
  33.  
  34.     public MemoryCache() {  
  35.         // 使用25%的可用的堆大小  
  36.         maxMemory = Runtime.getRuntime().maxMemory() / 4;  
  37.         Log.i(TAG, "MemoryCache will use up to " + (maxMemory / 1024 / 1024) + "MB");  
  38.     }  
  39.  
  40.     /**  
  41.      * 根據key獲取相應的圖片  
  42.      * @param key  
  43.      * @return Bitmap  
  44.      */ 
  45.     public Bitmap get(String key) {  
  46.         if (!cacheMap.containsKey(key)){  
  47.             return null;  
  48.         }  
  49.         return cacheMap.get(key);  
  50.     }  
  51.  
  52.     /**  
  53.      * 添加圖片到緩存  
  54.      * @param key  
  55.      * @param bitmap  
  56.      */ 
  57.     public synchronized void put(String key, Bitmap bitmap) {  
  58.         checkSize();  
  59.         cacheMap.put(key, bitmap);  
  60.          
  61.         Log.i(TAG, "cache size=" + cacheMap.size() + " bitmap size = " +  getBitmapSize(bitmap));  
  62.     }  
  63.  
  64.     /**  
  65.      * 嚴格控制堆內存,如果超過將首先替換最近最少使用的那個圖片緩存  
  66.      */ 
  67.     private void checkSize() {  
  68.         long count = 0;  
  69.         Iterator<Entry<String, Bitmap>> iterator = cacheMap.entrySet().iterator();  
  70.         while (iterator.hasNext()) {  
  71.             Entry<String, Bitmap> entry = iterator.next();  
  72.             count += getBitmapSize(entry.getValue());  
  73.         }  
  74.  
  75.         Log.i(TAG, "cache size=" + count + " length=" + cacheMap.size());  
  76.  
  77.         if (count > maxMemory) {  
  78.             while (iterator.hasNext()) {  
  79.                 Entry<String, Bitmap> entry = iterator.next();  
  80.                 count -= getBitmapSize(entry.getValue());  
  81.  
  82.                 iterator.remove();  
  83.                 if (count <= maxMemory) {  
  84.                     System.out.println("夠用了,不用在刪除了");  
  85.                     break;  
  86.                 }  
  87.             }  
  88.             Log.i(TAG, "Clean cache. New size " + cacheMap.size());  
  89.         }  
  90.     }  
  91.  
  92.     /**  
  93.      * 獲取bitmap的字節大小  
  94.      * @param bitmap  
  95.      * @return  
  96.      */ 
  97.     private long getBitmapSize(Bitmap bitmap) {  
  98.         if (bitmap == null) {  
  99.             return 0;  
  100.         }  
  101.         return bitmap.getRowBytes() * bitmap.getHeight();  
  102.     }  
  103.  
  104.     /**  
  105.      * 清空緩存  
  106.      */ 
  107.     public void clear() {  
  108.         cacheMap.clear();  
  109.     }  
  110.  
  111. }  

網絡下載文件本地緩存類

  1. package com.everyone.android.bitmap;  
  2.  
  3. import java.io.File;  
  4. import java.io.FileOutputStream;  
  5. import java.io.IOException;  
  6. import java.io.InputStream;  
  7. import java.text.SimpleDateFormat;  
  8. import java.util.Arrays;  
  9. import java.util.Comparator;  
  10.  
  11. import android.content.Context;  
  12. import android.os.StatFs;  
  13.  
  14. /**  
  15.  * 功能描述:網絡下載文件本地緩存類  
  16.  *   
  17.  * @author android_ls  
  18.  */ 
  19. public class FileCache {  
  20.  
  21.     /**  
  22.      * 本地與我們應用程序相關文件存放的根目錄  
  23.      */ 
  24.     private static final String ROOT_DIR_PATH = "CopyEveryone";  
  25.  
  26.     /**  
  27.      * 下載文件存放的目錄  
  28.      */ 
  29.     private static final String IMAGE_DOWNLOAD_CACHE_PATH = ROOT_DIR_PATH + "/Download/cache";  
  30.  
  31.     /**  
  32.      * 默認的磁盤緩存大小(20MB)  
  33.      */ 
  34.     private static final int DEFAULT_DISK_CACHE_SIZE = 1024 * 1024 * 20;  
  35.  
  36.     /**  
  37.      * 緩存文件存放目錄  
  38.      */ 
  39.     private File cacheDir;  
  40.  
  41.     /**  
  42.      * 緩存根目錄  
  43.      */ 
  44.     private String cacheRootDir;  
  45.       
  46.     private Context mContext;  
  47.  
  48.     public FileCache(Context context) {  
  49.         mContext = context;  
  50.           
  51.         if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {  
  52.             cacheRootDir = android.os.Environment.getExternalStorageDirectory().getAbsolutePath();  
  53.         } else {  
  54.             cacheRootDir = mContext.getCacheDir().getAbsolutePath();  
  55.         }  
  56.  
  57.         cacheDir = new File(cacheRootDir + File.separator + IMAGE_DOWNLOAD_CACHE_PATH);  
  58.         // 檢測文件緩存目錄是否存在,不存在則創建  
  59.         if (!cacheDir.exists()) {  
  60.             cacheDir.mkdirs();  
  61.         }  
  62.     }  
  63.  
  64.     /**  
  65.      * 獲取下載的文件要存放的緩存目錄  
  66.      * /mnt/sdcard/CopyEveryone/Download/cache  
  67.      * @return 緩存目錄的全路徑  
  68.      */ 
  69.     public String getCacheDirPath() {  
  70.         return cacheDir.getAbsolutePath();  
  71.     }  
  72.  
  73.     /**  
  74.      * 根據URL從文件緩存中獲取文件  
  75.      * @param url url的hashCode為緩存的文件名  
  76.      */ 
  77.     public File getFile(String url) {  
  78.         if (!cacheDir.exists()) {  
  79.             cacheDir.mkdirs();  
  80.         }  
  81.  
  82.         String filename = String.valueOf(url.hashCode());  
  83.         File file = new File(cacheDir, filename);  
  84.         return file;  
  85.     }  
  86.  
  87.     /**  
  88.      * 計算存儲可用的大小  
  89.      * @return  
  90.      */ 
  91.     public long getAvailableMemorySize() {  
  92.         StatFs stat = new StatFs(cacheRootDir);  
  93.         long blockSize = stat.getBlockSize();  
  94.         long availableBlocks = stat.getAvailableBlocks();  
  95.         return availableBlocks * blockSize;  
  96.     }  
  97.  
  98.     /**  
  99.      * 將指定的數據寫入文件  
  100.      * @param inputStream InputStream  
  101.      * @param outputStream OutputStream  
  102.      * @throws IOException   
  103.      */ 
  104.     public synchronized void writeToFile(InputStream inputStream, File file) throws IOException {  
  105.         int fileSize  = inputStream.available();  
  106.         System.out.println("fileSize = " + fileSize);  
  107.           
  108.         long enabledMemory  = getAvailableMemorySize();  
  109.         System.out.println("當前可用硬盤: " + (enabledMemory/1024/1024)); // 單位:MB  
  110.           
  111.         // 當前可用存儲空間不足20M  
  112.         if(DEFAULT_DISK_CACHE_SIZE > enabledMemory){  
  113.             if (fileSize > enabledMemory) {  
  114.                 // 檢測可用空間大小,若不夠用則刪除最早的文件  
  115.                 File[] files = cacheDir.listFiles();  
  116.                 Arrays.sort(files, new FileLastModifSort());  
  117.                   
  118.                 int length = files.length;  
  119.                 for (int i = 0; i < length; i++) {  
  120.                     files[i].delete();  
  121.                     length = files.length;  
  122.                       
  123.                     enabledMemory  = getAvailableMemorySize();  
  124.                     System.out.println("當前可用內存: " + enabledMemory);  
  125.                       
  126.                     if (fileSize <= enabledMemory) {  
  127.                         System.out.println("夠用了,不用在刪除了");  
  128.                         break;  
  129.                     }  
  130.                 }  
  131.             }  
  132.         } else {  
  133.             int count = 0;  
  134.             File[] files = cacheDir.listFiles();  
  135.             for (int i = 0; i < files.length; i++) {  
  136.                 count += files[i].length();  
  137.             }  
  138.               
  139.             System.out.println("file cache size = " + count);  
  140.               
  141.             // 使用的空間大於上限  
  142.             enabledMemory = DEFAULT_DISK_CACHE_SIZE - count;  
  143.             if(fileSize > enabledMemory){  
  144.                 Arrays.sort(files, new FileLastModifSort());  
  145.                   
  146.                 int length = files.length;  
  147.                 for (int i = 0; i < length; i++) {  
  148.                     count -= files[i].length();  
  149.                     files[i].delete();  
  150.                     length = files.length;  
  151.                      
  152.                     enabledMemory = DEFAULT_DISK_CACHE_SIZE - count;  
  153.                     if (fileSize <= enabledMemory) {  
  154.                         System.out.println("夠用了,不用在刪除了");  
  155.                         break;  
  156.                     }  
  157.                 }  
  158.             }  
  159.         }  
  160.           
  161.         if(enabledMemory == 0){  
  162.             return;  
  163.         }  
  164.           
  165.         // 將數據寫入文件保存  
  166.         FileOutputStream outStream = new FileOutputStream(file);  
  167.         byte[] buffer = new byte[1024];  
  168.         int len = 0;  
  169.         while ((len = inputStream.read(buffer)) != -1) {  
  170.             outStream.write(buffer, 0, len);  
  171.         }  
  172.         outStream.flush();  
  173.         outStream.close();  
  174.         inputStream.close();  
  175.           
  176.         // 設置最後修改的時間  
  177.         long newModifiedTime = System.currentTimeMillis();  
  178.         file.setLastModified(newModifiedTime);  
  179.           
  180.         System.out.println("file.length() = " + file.length());  
  181.           
  182.         SimpleDateFormat mDateFormat = new SimpleDateFormat ("yyyy年MM月dd日 HH:mm:ss");  
  183.         System.out.println("writeToFile file.lastModified() = " + mDateFormat.format(file.lastModified()));  
  184.     }  
  185.  
  186.    /**  
  187.     * 根據文件的最後修改時間進行排序  
  188.     * @author android_ls  
  189.     *  
  190.     */ 
  191.     class FileLastModifSort implements Comparator<File> {  
  192.         public int compare(File file1, File file2) {  
  193.             if (file1.lastModified() > file2.lastModified()) {  
  194.                 return 1;  
  195.             } else if (file1.lastModified() == file2.lastModified()) {  
  196.                 return 0;  
  197.             } else {  
  198.                 return -1;  
  199.             }  
  200.         }  
  201.     }  
  202.  
  203.     /**  
  204.      * 清空緩存的文件  
  205.      */ 
  206.     public void clear() {  
  207.         if (!cacheDir.exists()) {  
  208.             return;  
  209.         }  
  210.  
  211.         File[] files = cacheDir.listFiles();  
  212.         if (files != null) {  
  213.             for (File f : files) {  
  214.                 f.delete();  
  215.             }  
  216.         }  
  217.     }  
  218.  
  219. }  

圖片信息實體類

  1. package com.everyone.android.entity;  
  2.  
  3. import android.widget.ImageView;  
  4.  
  5. /**  
  6.  * 功能描述:圖片信息實體類  
  7.  *   
  8.  * @author android_ls  
  9.  */ 
  10. public class ImageInfo {  
  11.  
  12.     private int id; // 唯一標識  
  13.  
  14.     private ImageView imageView; // 用於顯示的組件  
  15.  
  16.     private String url; // 網絡URL  
  17.  
  18.     private int width; // 寬度  
  19.  
  20.     private int height; // 高度  
  21.  
  22.     private boolean rounded; // 是否要轉換成圓角  
  23.  
  24.     private boolean compress; // 是否要進行質量壓縮  
  25.  
  26.     public ImageInfo(ImageView imageView, String url) {  
  27.         this.imageView = imageView;  
  28.         this.url = url;  
  29.     }  
  30.  
  31.     public ImageInfo() {  
  32.     }  
  33.  
  34.     public ImageInfo(ImageView imageView, String url, int width, int height, boolean rounded, boolean compress) {  
  35.         this.imageView = imageView;  
  36.         this.url = url;  
  37.         this.width = width;  
  38.         this.height = height;  
  39.         this.rounded = rounded;  
  40.         this.compress = compress;  
  41.     }  
  42.  
  43.     public ImageInfo(ImageView imageView, String url, boolean rounded) {  
  44.         this.imageView = imageView;  
  45.         this.url = url;  
  46.         this.rounded = rounded;  
  47.     }  
  48.  
  49.     public ImageInfo(ImageView imageView, String url, int width, int height) {  
  50.         this.imageView = imageView;  
  51.         this.url = url;  
  52.         this.width = width;  
  53.         this.height = height;  
  54.     }  
  55.  
  56.     public ImageInfo(ImageView imageView, String url, int width, int height, boolean rounded) {  
  57.         this.imageView = imageView;  
  58.         this.url = url;  
  59.         this.width = width;  
  60.         this.height = height;  
  61.         this.rounded = rounded;  
  62.     }  
  63.  
  64.     public boolean isCompress() {  
  65.         return compress;  
  66.     }  
  67.  
  68.     public void setCompress(boolean compress) {  
  69.         this.compress = compress;  
  70.     }  
  71.  
  72.     public int getId() {  
  73.         return id;  
  74.     }  
  75.  
  76.     public void setId(int id) {  
  77.         this.id = id;  
  78.     }  
  79.  
  80.     public ImageView getImageView() {  
  81.         return imageView;  
  82.     }  
  83.  
  84.     public void setImageView(ImageView imageView) {  
  85.         this.imageView = imageView;  
  86.     }  
  87.  
  88.     public String getUrl() {  
  89.         return url;  
  90.     }  
  91.  
  92.     public void setUrl(String url) {  
  93.         this.url = url;  
  94.     }  
  95.  
  96.     public int getWidth() {  
  97.         return width;  
  98.     }  
  99.  
  100.     public void setWidth(int width) {  
  101.         this.width = width;  
  102.     }  
  103.  
  104.     public int getHeight() {  
  105.         return height;  
  106.     }  
  107.  
  108.     public void setHeight(int height) {  
  109.         this.height = height;  
  110.     }  
  111.  
  112.     public boolean isRounded() {  
  113.         return rounded;  
  114.     }  
  115.  
  116.     public void setRounded(boolean rounded) {  
  117.         this.rounded = rounded;  
  118.     }  
  119.  
  120. }  
  121.  

Bitmap加工處理工具類

  1. package com.everyone.android.utils;  
  2.  
  3. import java.io.ByteArrayOutputStream;  
  4. import java.io.File;  
  5. import java.io.IOException;  
  6. import java.io.InputStream;  
  7.  
  8. import android.graphics.Bitmap;  
  9. import android.graphics.Bitmap.Config;  
  10. import android.graphics.BitmapFactory;  
  11. import android.graphics.Canvas;  
  12. import android.graphics.Color;  
  13. import android.graphics.Paint;  
  14. import android.graphics.PorterDuff;  
  15. import android.graphics.PorterDuff.Mode;  
  16. import android.graphics.PorterDuffXfermode;  
  17. import android.graphics.Rect;  
  18. import android.graphics.RectF;  
  19. import android.graphics.drawable.BitmapDrawable;  
  20. import android.graphics.drawable.Drawable;  
  21.  
  22. /**  
  23.  * 功能描述:Bitmap加工處理工具類  
  24.  * @author android_ls  
  25.  *  
  26.  */ 
  27. public class BitmapUtil {  
  28.  
  29.     /**  
  30.      * 將圖片變成圓角(方法一)  
  31.      * @param bitmap Bitmap  
  32.      * @param pixels 圓角的弧度  
  33.      * @return 圓角圖片  
  34.      */ 
  35.     public static Bitmap drawRoundBitmap(Bitmap bitmap, float pixels) {  
  36.         Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);  
  37.         Canvas canvas = new Canvas(output);  
  38.  
  39.         final Paint paint = new Paint();  
  40.         final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());  
  41.         final RectF rectF = new RectF(rect);  
  42.  
  43.         paint.setAntiAlias(true);  
  44.         canvas.drawARGB(0, 0, 0, 0);  
  45.         // paint.setColor()的參數,除不能為Color.TRANSPARENT外,可以任意寫  
  46.         paint.setColor(Color.RED);  
  47.         canvas.drawRoundRect(rectF, pixels, pixels, paint);  
  48.  
  49.         paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));  
  50.         canvas.drawBitmap(bitmap, rect, rect, paint);  
  51.  
  52.         return output;  
  53.     }  
  54.  
  55.     /**  
  56.      * 將圖片變成圓角(方法二)  
  57.      * @param bitmap Bitmap  
  58.      * @param pixels 圓角的弧度  
  59.      * @return 圓角圖片  
  60.      */ 
  61.     public static Bitmap drawRoundCorner(Bitmap bitmap, float pixels) {  
  62.         Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);  
  63.         Canvas canvas = new Canvas(output);  
  64.  
  65.         RectF outerRect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight());  
  66.         Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);  
  67.         // paint.setColor()的參數,除不能為Color.TRANSPARENT外,可以任意寫  
  68.         paint.setColor(Color.WHITE);  
  69.         canvas.drawRoundRect(outerRect, pixels, pixels, paint);  
  70.  
  71.         paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));  
  72.         Drawable drawable = new BitmapDrawable(bitmap);  
  73.         drawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());  
  74.         canvas.saveLayer(outerRect, paint, Canvas.ALL_SAVE_FLAG);  
  75.         drawable.draw(canvas);  
  76.         canvas.restore();  
  77.  
  78.         return output;  
  79.     }  
  80.  
  81.     /**  
  82.      * 對Bitmap進行質量壓縮  
  83.      * @param bitmap Bitmap  
  84.      * @return ByteArrayInputStream  
  85.      */ 
  86.     public static Bitmap compressBitmap(Bitmap bitmap) {  
  87.         ByteArrayOutputStream outStream = new ByteArrayOutputStream();  
  88.         // 圖片質量默認值為100,表示不壓縮  
  89.         int quality = 100;  
  90.         // PNG是無損的,將會忽略質量設置。因此,這裡設置為JPEG  
  91.         bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outStream);  
  92.  
  93.         // 判斷壓縮後圖片的大小是否大於100KB,大於則繼續壓縮  
  94.         while (outStream.toByteArray().length / 1024 > 100) {  
  95.             outStream.reset();  
  96.  
  97.             // 壓縮quality%,把壓縮後的數據存放到baos中  
  98.             bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outStream);  
  99.             quality -= 10;  
  100.         }  
  101.  
  102.         System.out.println("quality = " + quality);  
  103.  
  104.         byte[] data = outStream.toByteArray();  
  105.         return BitmapFactory.decodeByteArray(data, 0, data.length);  
  106.     }  
  107.  
  108.     /**  
  109.      * 根據指定的壓縮比例,獲得合適的Bitmap(方法一)  
  110.      * @param file File  
  111.      * @param width 指定的寬度  
  112.      * @param height 指定的高度  
  113.      * @return Bitmap  
  114.      */ 
  115.     public static Bitmap decodeStream(File file, int width, int height) {  
  116.         BitmapFactory.Options options = new BitmapFactory.Options();  
  117.         options.inJustDecodeBounds = true;  
  118.         BitmapFactory.decodeFile(file.getAbsolutePath(), options);  
  119.  
  120.         int w = options.outWidth;  
  121.         int h = options.outHeight;  
  122.  
  123.         // 從服務器端獲取的圖片大小為:80x120  
  124.         // 我們想要的圖片大小為:40x40  
  125.         // 縮放比:120/40 = 3,也就是說我們要的圖片大小為原圖的1/3  
  126.  
  127.         // 縮放比。由於是固定比例縮放,只用高或者寬其中一個數據進行計算即可  
  128.         int ratio = 1; // 默認為不縮放  
  129.         if (w >= h && w > width) {  
  130.             ratio = (int) (w / width);  
  131.         } else if (w < h && h > height) {  
  132.             ratio = (int) (h / height);  
  133.         }  
  134.  
  135.         if (ratio <= 0) {  
  136.             ratio = 1;  
  137.         }  
  138.  
  139.         System.out.println("圖片的縮放比例值ratio = " + ratio);  
  140.  
  141.         options = new BitmapFactory.Options();  
  142.         options.inJustDecodeBounds = false;  
  143.         // 屬性值inSampleSize表示縮略圖大小為原始圖片大小的幾分之一,即如果這個值為2,  
  144.         // 則取出的縮略圖的寬和高都是原始圖片的1/2,圖片大小就為原始大小的1/4。  
  145.         options.inSampleSize = ratio;  
  146.  
  147.         return BitmapFactory.decodeFile(file.getAbsolutePath(), options);  
  148.     }  
  149.  
  150.     /**  
  151.      * 根據指定的壓縮比例,獲得合適的Bitmap(方法二)  
  152.      * @param inStream InputStream  
  153.      * @param width 指定的寬度  
  154.      * @param height 指定的高度  
  155.      * @return Bitmap  
  156.      * @throws IOException  
  157.      */ 
  158.     public static Bitmap decodeStream(InputStream inStream, int width, int height) throws IOException {  
  159.         BitmapFactory.Options options = new BitmapFactory.Options();  
  160.         options.inJustDecodeBounds = true;  
  161.  
  162.         // 從輸入流讀取數據  
  163.         byte[] data = StreamTool.read(inStream);  
  164.         BitmapFactory.decodeByteArray(data, 0, data.length, options);  
  165.  
  166.         int w = options.outWidth;  
  167.         int h = options.outHeight;  
  168.  
  169.         // 從服務器端獲取的圖片大小為:80x120  
  170.         // 我們想要的圖片大小為:40x40  
  171.         // 縮放比:120/40 = 3,也就是說我們要的圖片大小為原圖的1/3  
  172.  
  173.         // 縮放比。由於是固定比例縮放,只用高或者寬其中一個數據進行計算即可  
  174.         int ratio = 1; // 默認為不縮放  
  175.         if (w >= h && w > width) {  
  176.             ratio = (int) (w / width);  
  177.         } else if (w < h && h > height) {  
  178.             ratio = (int) (h / height);  
  179.         }  
  180.  
  181.         if (ratio <= 0) {  
  182.             ratio = 1;  
  183.         }  
  184.  
  185.         System.out.println("圖片的縮放比例值ratio = " + ratio);  
  186.  
  187.         options.inJustDecodeBounds = false;  
  188.         // 屬性值inSampleSize表示縮略圖大小為原始圖片大小的幾分之一,即如果這個值為2,  
  189.         // 則取出的縮略圖的寬和高都是原始圖片的1/2,圖片大小就為原始大小的1/4。  
  190.         options.inSampleSize = ratio;  
  191.         return BitmapFactory.decodeByteArray(data, 0, data.length);  
  192.     }  
  193.  
  194.     /**  
  195.      * 根據指定的壓縮比例,獲得合適的Bitmap(會出錯的方法,僅用於測試)  
  196.      * @param inStream  
  197.      * @param width  
  198.      * @param height  
  199.      * @return  
  200.      * @throws IOException  
  201.      */ 
  202.     public static Bitmap decodeStreamError(InputStream inStream, int width, int height) throws IOException {  
  203.         BitmapFactory.Options options = new BitmapFactory.Options();  
  204.         options.inJustDecodeBounds = true;  
  205.         BitmapFactory.decodeStream(inStream, null, options);  
  206.  
  207.         int w = options.outWidth;  
  208.         int h = options.outHeight;  
  209.  
  210.         // 從服務器端獲取的圖片大小為:80x120  
  211.         // 我們想要的圖片大小為:40x40  
  212.         // 縮放比:120/40 = 3,也就是說我們要的圖片大小為原圖的1/3  
  213.  
  214.         // 縮放比。由於是固定比例縮放,只用高或者寬其中一個數據進行計算即可  
  215.         int ratio = 1; // 默認為不縮放  
  216.         if (w >= h && w > width) {  
  217.             ratio = (int) (w / width);  
  218.         } else if (w < h && h > height) {  
  219.             ratio = (int) (h / height);  
  220.         }  
  221.  
  222.         if (ratio <= 0) {  
  223.             ratio = 1;  
  224.         }  
  225.  
  226.         System.out.println("圖片的縮放比例值ratio = " + ratio);  
  227.  
  228.         options.inJustDecodeBounds = false;  
  229.         // 屬性值inSampleSize表示縮略圖大小為原始圖片大小的幾分之一,即如果這個值為2,  
  230.         // 則取出的縮略圖的寬和高都是原始圖片的1/2,圖片大小就為原始大小的1/4。  
  231.         options.inSampleSize = ratio;  
  232.  
  233.         return BitmapFactory.decodeStream(inStream, null, options);  
  234.     }  
  235.  
  236. }  
  237.  


單位轉換工具類

  1. package com.everyone.android.utils;  
  2.  
  3. import android.content.Context;  
  4.  
  5. /**  
  6.  * 功能描述:單位轉換工具類  
  7.  * @author android_ls  
  8.  *  
  9.  */ 
  10. public class DensityUtil {  
  11.  
  12.     /**  
  13.      * 將單位為dip的值轉換成單位為px的值  
  14.      * @param context Context  
  15.      * @param dipValue dip值  
  16.      * @return px值  
  17.      */ 
  18.     public static int dip2px(Context context, float dipValue) {  
  19.         final float scale = context.getResources().getDisplayMetrics().density;  
  20.         return (int) (dipValue * scale + 0.5f);  
  21.     }  
  22.  
  23.     /**  
  24.      * 將單位為px的值轉換成單位為dip的值  
  25.      * @param context Context  
  26.      * @param pxValue 像素值  
  27.      * @return dip值  
  28.      */ 
  29.     public static int px2dip(Context context, float pxValue) {  
  30.         final float scale = context.getResources().getDisplayMetrics().density;  
  31.         return (int) (pxValue / scale + 0.5f);  
  32.     }  
  33.  
  34.     /**  
  35.      * 將px值轉換為sp值,保證文字大小不變  
  36.      *   
  37.      * @param pxValue  
  38.      * @param fontScale(DisplayMetrics類中屬性scaledDensity)  
  39.      * @return  
  40.      */ 
  41.     public static int px2sp(Context context, float pxValue) {  
  42.         final float scale = context.getResources().getDisplayMetrics().density;  
  43.         return (int) (pxValue / scale + 0.5f);  
  44.     }  
  45.  
  46.     /**  
  47.      * 將sp值轉換為px值,保證文字大小不變  
  48.      *   
  49.      * @param spValue  
  50.      * @param fontScale(DisplayMetrics類中屬性scaledDensity)  
  51.      * @return  
  52.      */ 
  53.     public static int sp2px(Context context, float spValue) {  
  54.         final float scale = context.getResources().getDisplayMetrics().density;  
  55.         return (int) (spValue * scale + 0.5f);  
  56.     }  
  57. }  


數據流處理工具類數據流處理工具類數據流處理工具類

  1. package com.everyone.android.utils;  
  2.  
  3. import java.io.ByteArrayOutputStream;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6.  
  7. /**  
  8.  * 功能描述:數據流處理工具類  
  9.  * @author android_ls  
  10.  */ 
  11. public final class StreamTool {  
  12.  
  13.     /**  
  14.      * 從輸入流讀取數據  
  15.      *   
  16.      * @param inStream  
  17.      * @return  
  18.      * @throws IOException  
  19.      * @throws Exception  
  20.      */ 
  21.     public static byte[] read(InputStream inStream) throws IOException {  
  22.         ByteArrayOutputStream outSteam = new ByteArrayOutputStream();  
  23.         byte[] buffer = new byte[1024];  
  24.         int len = 0;  
  25.         while ((len = inStream.read(buffer)) != -1) {  
  26.             outSteam.write(buffer, 0, len);  
  27.         }  
  28.         outSteam.close();  
  29.         inStream.close();  
  30.         return outSteam.toByteArray();  
  31.     }  
  32.  
  33. }  
  34.  

五、網絡模塊修改的文件源碼:

      網絡請求線程基類

  1. package com.everyone.android.net;  
  2.  
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.io.Serializable;  
  6. import java.net.HttpURLConnection;  
  7. import java.util.Map;  
  8.  
  9. import org.json.JSONException;  
  10.  
  11. import com.everyone.android.callback.ParseCallback;  
  12. import com.everyone.android.callback.ResultCallback;  
  13. import com.everyone.android.utils.Constant;  
  14. import com.everyone.android.utils.LogUtil;  
  15. import com.everyone.android.utils.StreamTool;  
  16.  
  17. /**  
  18.  * 功能描述:網絡請求線程基類  
  19.  * @author android_ls  
  20.  *  
  21.  */ 
  22. public abstract class AsyncBaseRequest implements Runnable, Serializable {  
  23.     /**  
  24.      *   
  25.      */ 
  26.     private static final long serialVersionUID = 1L;  
  27.  
  28.     /**  
  29.      * LOG打印標簽  
  30.      */ 
  31.     private static final String TAG = "AsyncBaseRequest";  
  32.       
  33.     /**  
  34.      * 網絡連接超時,默認值為5秒  
  35.      */ 
  36.     protected int connectTimeout = 5 * 1000;  
  37.  
  38.     /**  
  39.      * 網絡數據讀取超時,默認值為5秒  
  40.      */ 
  41.     protected int readTimeout = 5 * 1000;  
  42.  
  43.     private boolean interrupted;  
  44.  
  45.     public boolean isInterrupted() {  
  46.         return interrupted;  
  47.     }  
  48.  
  49.     public void setInterrupted(boolean interrupted) {  
  50.         this.interrupted = interrupted;  
  51.     }  
  52.  
  53.     protected void setConnectTimeout(int connectTimeout) {  
  54.         this.connectTimeout = connectTimeout;  
  55.     }  
  56.  
  57.     protected void setReadTimeout(int readTimeout) {  
  58.         this.readTimeout = readTimeout;  
  59.     }  
  60.  
  61.     protected String requestUrl;  
  62.  
  63.     protected Map<String, String> parameter;  
  64.  
  65.     private ParseCallback parseHandler;  
  66.  
  67.     private ResultCallback requestCallback;  
  68.  
  69.     protected HttpURLConnection mHttpURLConn;  
  70.  
  71.     protected InputStream mInStream;  
  72.  
  73.     public AsyncBaseRequest(String url, Map<String, String> parameter, ParseCallback handler, ResultCallback requestCallback) {  
  74.         this.parseHandler = handler;  
  75.         this.requestUrl = url;  
  76.         this.parameter = parameter;  
  77.         this.requestCallback = requestCallback;  
  78.     }  
  79.  
  80.     /**  
  81.      * 發送網絡請求  
  82.      *   
  83.      * @return 網絡請求返回的InputStream數據流  
  84.      * @throws IOException  
  85.      */ 
  86.     protected abstract InputStream getRequestResult() throws IOException;  
  87.  
  88.     @Override 
  89.     public void run() {  
  90.         if (interrupted) {  
  91.             LogUtil.i(TAG, "訪問網絡前中斷業務處理線程(終止)");  
  92.             return;  
  93.         }  
  94.           
  95.         try {  
  96.             mInStream = getRequestResult();  
  97.             if (mInStream != null) {  
  98.                 if (interrupted) {  
  99.                     LogUtil.i(TAG, "讀取數據前中斷業務處理線程(終止)");  
  100.                     return;  
  101.                 }  
  102.  
  103.                 Object obj = null;  
  104.                 if(parseHandler != null){  
  105.                     byte[] data = StreamTool.read(mInStream);  
  106.                     if (interrupted) {  
  107.                         LogUtil.i(TAG, "解析數據前中斷業務處理線程(終止)");  
  108.                         return;  
  109.                     }  
  110.                       
  111.                     String result = new String(data);  
  112.                     obj = parseHandler.parse(result);  
  113.                 }  
  114.                   
  115.                 if (interrupted) {  
  116.                     LogUtil.i(TAG, "刷新UI前中斷業務處理線程(終止)");  
  117.                     return;  
  118.                 }  
  119.                   
  120.                 if(obj != null){  
  121.                     requestCallback.onSuccess(obj);  
  122.                 } else {  
  123.                     requestCallback.onSuccess(mInStream);  
  124.                 }  
  125.                  
  126.             } else {  
  127.                 LogUtil.i(TAG, "get InputStream By HttpURLConnection return result is NULL.");  
  128.                 requestCallback.onFail(Constant.NETWORK_REQUEST_RETUN_NULL); // 網絡請求返回NULL  
  129.             }  
  130.         } catch (JSONException e) {  
  131.             requestCallback.onFail(Constant.NETWORK_REQUEST_RESULT_PARSE_ERROR); // 網絡請求返回結果解析出錯  
  132.             e.printStackTrace();  
  133.         } catch (IOException e) {  
  134.             requestCallback.onFail(Constant.NETWORK_REQUEST_IOEXCEPTION_CODE); // IO異常標識  
  135.             e.printStackTrace();  
  136.         }  
  137.           
  138.     }  
  139.  
  140.     public HttpURLConnection getRequestConn() {  
  141.         return mHttpURLConn;  
  142.     }  
  143.  
  144. }  
  145.  

      通過HTTP協議發送GET請求

  1. package com.everyone.android.net;  
  2.  
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.net.HttpURLConnection;  
  6. import java.net.URL;  
  7. import java.net.URLEncoder;  
  8. import java.util.Map;  
  9.  
  10. import org.apache.http.protocol.HTTP;  
  11.  
  12. import com.everyone.android.callback.ParseCallback;  
  13. import com.everyone.android.callback.ResultCallback;  
  14.  
  15. /**  
  16.  * 功能描述:通過HTTP協議發送GET請求  
  17.  * @author android_ls  
  18.  *  
  19.  */ 
  20. public class AsyncHttpGet extends AsyncBaseRequest {  
  21.  
  22.     /**  
  23.      *   
  24.      */ 
  25.     private static final long serialVersionUID = 2L;  
  26.  
  27.     public AsyncHttpGet(String url, Map<String, String> parameter, ParseCallback handler, ResultCallback requestCallback) throws IOException {  
  28.         super(url, parameter, handler, requestCallback);  
  29.     }  
  30.  
  31.     @Override 
  32.     protected InputStream getRequestResult() throws IOException {  
  33.         StringBuilder sb = new StringBuilder(requestUrl);  
  34.         if (parameter != null && !parameter.isEmpty()) {  
  35.             sb.append('?');  
  36.             for (Map.Entry<String, String> entry : parameter.entrySet()) {  
  37.                 sb.append(entry.getKey()).append('=').append(URLEncoder.encode(entry.getValue(), HTTP.UTF_8)).append('&');  
  38.             }  
  39.             sb.deleteCharAt(sb.length() - 1);  
  40.         }  
  41.  
  42.         URL url = new URL(sb.toString());  
  43.         mHttpURLConn = (HttpURLConnection) url.openConnection();  
  44.         mHttpURLConn.setConnectTimeout(connectTimeout);  
  45.         mHttpURLConn.setRequestMethod("GET");  
  46.         if (mHttpURLConn.getResponseCode() == HttpURLConnection.HTTP_OK) {  
  47.             return mHttpURLConn.getInputStream();  
  48.         }  
  49.         return null;  
  50.     }  
  51.  
  52. }  
  53.  


六、運行後的效果圖:

 

轉自:http://blog.csdn.net/android_ls/article/details/8797740

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved