【開源畢設】一款精美的家校互動APP分享——愛吖校推 [你關注的,咱們才推](持續開源更新3)附高效動態壓縮Bitmap

1、寫在前面php

  愛吖校推如同它的名字同樣,是一款校園類信息推送交流平臺,這麼多的家校互動類軟件,你選擇了我,這是個人幸運。
從第一次在博客園上寫博客到如今,我一次一次地提升博文的質量和代碼的可讀性,都是爲了大家,由於有大家,纔有我。 我從一個一個的demo到從0開始作這個app,一路歷經艱難險阻,期待你與我進行心靈交流。由於我也曾遇到各類棘手的問題,處處詢問不到答案, 那個時候的我,也許正如如今的你。而我,也還在這條道路上默默前行。html

  前面兩期地址:【開源畢設】一款精美的家校互動APP分享——愛吖校推 [你關注的,咱們才推](持續開源更新)前端

         【開源畢設】一款精美的家校互動APP分享——愛吖校推 [你關注的,咱們才推](持續開源更新2)android

  小夥伴們,寶寶又來了,是的,愛吖校推又實現了新功能,此次給你們帶來的是什麼呢?此次是客服系統,推送系統和圖片發送以及動態更新的功能更新,如今APP支持圖片壓縮上傳,採用eventbus動態刷新UI,而且同一個圈子的人能收到相應人員發送的消息動態啦!!對,不只是android,php服務器也相應獲得了更新,還在猶豫什麼?快下載看看吧~git

2、一樣的有用之處程序員

  

  1)經過本項目你能夠拿到你想要的自定義控件效果;github

  2)android純前端程序員也能瞭解到如何用php編寫api接口,讓項目數據動起來;api

  3)有意轉後臺的程序員能夠學到更多邏輯方面有用的知識;數組

  4)對,若是你是初學者,你可能會獲得一位前行良友;緩存

  5)玩什麼遊戲,安心擼代碼吧!

  6)對,這不僅是android,這不僅是php,這還有文檔,沒錯,就是開源!!!

  7)圖片佔用內存泄漏?這裏有手把手教你封裝的bitmapUtil。

3、上個效果圖唄

      

4、下一步要作的

  1)加入微信小視頻功能

  2)優化演示圖中出現的內存泄漏

  3) 減少資源體積

5、幫你們安利一下開發必過的坑——圖片經常致使OOM

  1)你們必定都知道,手機相機拍照的圖片都是幾千像素的,而咱們的手機屏幕卻通常是720的,而且一張大圖,動則幾M,上傳起來用戶流量着實受不了,那麼壓縮資源體積就變得至關麻煩了,這裏就給你們講解一下壓縮上傳的正確姿式。

 

  2)我相信做爲coder的你,必定知道Bitmap是引發OOM的罪魁禍首之一,因此咱們必定爲了節約內存,通常都會在服務器上緩存一個縮略圖,這樣不但能夠提高下載速度,減小用戶流量,還達到了很好的節約內存的目的。

  要是咱們能把bitmap設置爲imageView的大小,根據要顯示的ImageView來壓縮Bitmap那確定最好了。

  根據這樣的思路,咱們確定得首先算出imageView的寬高,這個很簡單;直接imageView.getWidth()和imageView.getHeight()方法就能夠達到目的。

  3)若是你操做圖片,你必定知道BitmapFatory,由於咱們一般使用它來操做圖片。

     BitmapFactory這個類提供了多個解析方法(decodeByteArray,decodeFile,decodeResource等)用來建立bitmap對象,其中sd卡圖片用decodeFile,傳入path路徑和Options就能夠了,而網絡圖片咱們一般使用decodeStream方法,資源文件採用decodeResource;

    然而這些方法,都會爲bitmap分配內存,圖片太大必定會致使OOM的,因此咱們須要先進行壓縮,使用BitmapFatory.Options。

  4)BitmapFactory.Options碎碎念

    它有一個inJustDecodeBounds屬性,當這個屬性爲true的時候,調用上面三個方法返回的就不是一個完整的bitmap對象,而是null。由於它禁止這些方法爲bitmap分配內存,當時設置這個屬性爲true的時候,Options的outWidth,outHeight和outMimeType屬性就會被複制。這樣咱們就能夠在加載圖片以前獲取到圖片的長寬和MIME類型。就等於不讀取這個圖片,卻獲取到了它的參數,的確很6。

    說到這裏,必須說到一個很6的屬性了,inSampleSize,能夠理解爲壓縮比率,設置好這個比率,就能調用上面的decodeXXXX方法得到縮略圖了,若是圖片大小都一致,那還能夠定死它,可咱們的圖片卻大小不一,那咱們應該如何得到正確的inSampleSize值呢?能夠經過下面的方法,動態計算。

 1   /**
 2      * @description 計算圖片的壓縮比率
 3      *
 4      * @param options 參數
 5      * @param reqWidth 目標的寬度
 6      * @param reqHeight 目標的高度
 7      * @return
 8      */
 9     private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
10         // 源圖片的高度和寬度
11         final int height = options.outHeight;
12         final int width = options.outWidth;
13         int inSampleSize = 1;
14         if (height > reqHeight || width > reqWidth) {
15             final int halfHeight = height / 2;
16             final int halfWidth = width / 2;
17             // Calculate the largest inSampleSize value that is a power of 2 and keeps both
18             // height and width larger than the requested height and width.
19             while ((halfHeight / inSampleSize) > reqHeight
20                     && (halfWidth / inSampleSize) > reqWidth) {
21                 inSampleSize *= 2;
22             }
23         }
24         return inSampleSize;
25     }

  然而,事實卻不如咱們想象那麼美好,inSampleSize官方註釋告訴咱們一個必須注意的點:由於inSampleSize只能是2的整數次冪,意味着若是上面咱們算出來inSampleSize爲6的話,這時候只能向下取得整數次冪,就是4。這樣設計的緣由極可能是爲了漸變bitmap壓縮,畢竟按照2的次方進行壓縮會比較高效和方便。

  那趕上這樣的問題,確定是沒法達到咱們想要的效果的,好比咱們計算出來的inSampleSize是15,向下取就成了8,明顯差距太大。那有沒有一種方法達到咱們的效果呢?

  答案是確定的!

  5)再次壓縮

  別忽略了Bitmap有這麼一個方法:createScaleBitmap!!

  這個方法能夠給咱們按照要求拉伸/縮小一個bitmap,咱們能夠經過這個方法把咱們以前獲得的較大的縮略圖進行縮小,讓其徹底符合咱們的需求。

  

 1 /**
 2      * @description 經過傳入的bitmap,進行壓縮,獲得符合標準的bitmap
 3      *
 4      * @param src
 5      * @param dstWidth
 6      * @param dstHeight
 7      * @return
 8      */
 9     private static Bitmap createScaleBitmap(Bitmap src, int dstWidth, int dstHeight, int inSampleSize) {
10         //若是inSampleSize是2的倍數,也就說這個src已是咱們想要的縮略圖了,直接返回便可。
11         if (inSampleSize % 2 == 0) {
12             return src;
13         }
14         // 若是是放大圖片,filter決定是否平滑,若是是縮小圖片,filter無影響,咱們這裏是縮小圖片,因此直接設置爲false
15         Bitmap dst = Bitmap.createScaledBitmap(src, dstWidth, dstHeight, false);
16         if (src != dst) { // 若是沒有縮放,那麼不回收
17             src.recycle(); // 釋放Bitmap的native像素數組
18         }
19         return dst;
20     }

  或許你會問,爲啥要先從inSampleSize產生一個縮略圖A,而不直接經過createScaseBitmap()方法縮放呢?

  由於若是要從原始的圖片直接縮放的話,就須要把原始圖片直接放入內存 中,這將十分危險!!!先經過inSmapleSize獲得一個較大的縮略圖,它會比原圖小不少,直接加載到內存中再進行拉伸/縮小就比較安全了!

  6)完整代碼:

  1 package com.example.nanchen.aiyaschoolpush.utils;
  2 
  3 import android.content.res.Resources;
  4 import android.graphics.Bitmap;
  5 import android.graphics.BitmapFactory;
  6 
  7 /**
  8  *
  9  * bitmap相關操做工具類
 10  *
 11  * @author nanchen
 12  * @fileName AiYaSchoolPush
 13  * @packageName com.example.nanchen.aiyaschoolpush.utils
 14  * @date 2016/11/28  09:45
 15  */
 16 
 17 public class BitmapUtil {
 18 
 19     /**
 20      * @description 計算圖片的壓縮比率
 21      *
 22      * @param options 參數
 23      * @param reqWidth 目標的寬度
 24      * @param reqHeight 目標的高度
 25      * @return
 26      */
 27     private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
 28         // 源圖片的高度和寬度
 29         final int height = options.outHeight;
 30         final int width = options.outWidth;
 31         int inSampleSize = 1;
 32         if (height > reqHeight || width > reqWidth) {
 33             final int halfHeight = height / 2;
 34             final int halfWidth = width / 2;
 35             // Calculate the largest inSampleSize value that is a power of 2 and keeps both
 36             // height and width larger than the requested height and width.
 37             while ((halfHeight / inSampleSize) > reqHeight
 38                     && (halfWidth / inSampleSize) > reqWidth) {
 39                 inSampleSize *= 2;
 40             }
 41         }
 42         return inSampleSize;
 43     }
 44 
 45     /**
 46      * @description 從Resources中加載圖片
 47      *
 48      * @param res
 49      * @param resId
 50      * @param reqWidth
 51      * @param reqHeight
 52      * @return
 53      */
 54     public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
 55         final BitmapFactory.Options options = new BitmapFactory.Options();
 56         options.inJustDecodeBounds = true; // 設置成了true,不佔用內存,只獲取bitmap寬高
 57         BitmapFactory.decodeResource(res, resId, options); // 讀取圖片長款
 58         options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // 調用上面定義的方法計算inSampleSize值
 59         // 使用獲取到的inSampleSize值再次解析圖片
 60         options.inJustDecodeBounds = false;
 61         Bitmap src = BitmapFactory.decodeResource(res, resId, options); // 載入一個稍大的縮略圖
 62         return createScaleBitmap(src, reqWidth, reqHeight, options.inSampleSize); // 進一步獲得目標大小的縮略圖
 63     }
 64 
 65     /**
 66      * @description 經過傳入的bitmap,進行壓縮,獲得符合標準的bitmap
 67      *
 68      * @param src
 69      * @param dstWidth
 70      * @param dstHeight
 71      * @return
 72      */
 73     private static Bitmap createScaleBitmap(Bitmap src, int dstWidth, int dstHeight, int inSampleSize) {
 74         //若是inSampleSize是2的倍數,也就說這個src已是咱們想要的縮略圖了,直接返回便可。
 75         if (inSampleSize % 2 == 0) {
 76             return src;
 77         }
 78         // 若是是放大圖片,filter決定是否平滑,若是是縮小圖片,filter無影響,咱們這裏是縮小圖片,因此直接設置爲false
 79         Bitmap dst = Bitmap.createScaledBitmap(src, dstWidth, dstHeight, false);
 80         if (src != dst) { // 若是沒有縮放,那麼不回收
 81             src.recycle(); // 釋放Bitmap的native像素數組
 82         }
 83         return dst;
 84     }
 85 
 86     /**
 87      * @description 從SD卡上加載圖片
 88      *
 89      * @param pathName
 90      * @param reqWidth
 91      * @param reqHeight
 92      * @return
 93      */
 94     public static Bitmap decodeSampledBitmapFromFile(String pathName, int reqWidth, int reqHeight) {
 95         final BitmapFactory.Options options = new BitmapFactory.Options();
 96         options.inJustDecodeBounds = true;
 97         BitmapFactory.decodeFile(pathName, options);
 98         options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
 99         options.inJustDecodeBounds = false;
100         Bitmap src = BitmapFactory.decodeFile(pathName, options);
101         return createScaleBitmap(src, reqWidth, reqHeight, options.inSampleSize);
102     }
103 }

6、寫在最後

  好噠,第三期就介紹到這裏啦,喜歡的話就去github下載下來體驗吧~(PS:樓主服務器目前是採用xampp搭建的本地服務器,外網暫沒法訪問,須要體驗效果請自行搭建服務器,見樓主前面博客:【定有驚喜】android程序員如何作本身的API接口?php與android的良好交互(附環境搭建),讓前端數據動起來~

  github地址:https://github.com/nanchen2251/AiYaSchoolPush

  開源不易,別忘了點點推薦,點點star,轉載請珍惜做者的勞動成果,謝謝。

相關文章
相關標籤/搜索