標籤:系統 空手套白狼 als 手機 string and ref uitable static
Android非同步載入全解析之大圖處理非同步載入中很重要的一部分就是對映像的處理,這也是我們前面用非同步載入映像做樣本的原因。
一方面是由於影像處理不好的話會很占記憶體,並且easyOOM,還有一方面,映像也比文字要大,載入比較慢。所以,在解說了怎樣進行多線程、AsyncTask進行多線程載入後,先暫停下後面的學習。來對映像的非同步處理進行一些最佳化工作。
為什麼要對影像處理為什麼要對映像進行處理,這是一個很直接的問題。一張映像。無論你拿手機、相機、單反還是什麼玩意拍出來,它就有一定的大小,可是在不同的終端上,終端也有不同的大小。比方一張超高請無碼大圖,10M大小,在網頁中看著挺爽。全高清,毛孔都看得清。
相同一張圖片。假設放在4.7寸的手機上,當然,相同還是一張高清無碼大圖,但這張圖片10M,在電腦上可能不算什麼,但在手機上,已經是很大了,而這張圖片在手機上,你拚命看。也就是那樣,即使解析度降低一半。你看上去也還是差點兒相同。
這就像所謂的視網膜屏、2k屏、4k屏,事實上已經基本達到視覺分析的極限了。一般情況下,區別並不大。
可是,儘管你看著區別不大,但對系統來說。區別就很大了,手機的記憶體。要像使用你藏的私房錢一樣,每一分都要三思而用。
所以。我們在下載高解析度的圖片的時候。能夠對映像進行壓縮,顯示上儘管沒有太大區別,可是卻幫系統節省了大量的私房錢。
BitmapFactory之inSampleSizeBitmapFactory是Android中提供的對映像的解析方法。通過它的一些靜態方法。我們能夠對映像進行解析。比如從檔案裡解析——decodeFile;從資源中解析——decodeResource。從網路中解析——decodeStream等等。當我們從網路上進行映像下載的時候,看情況,是否須要對映像進行壓縮,那麼怎樣在系統不載入映像到記憶體之前,就擷取映像的大小等參數呢?看上去很矛盾,但系統給我們提供了一種簡單的解決方案。BitmapFactory提供了BitmapFactory.Options參數。這個參數有一個inJustDecodeBounds屬性。當這個屬性為true的時候,我們就能夠禁止系統載入映像到記憶體。可是。!!
這時候,Options參數中的映像寬高、類型等屬性已經被賦值了,這樣。我們就實現了空手套白狼,哦,不正確,是不使用記憶體就擷取映像的屬性。
BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeResource(getResources(), R.id.myimage, options);// 擷取屬性值int imageHeight = options.outHeight;int imageWidth = options.outWidth;String imageType = options.outMimeType;
在獲得了映像的參數之後,我們就能夠對映像進行對應的處理了。比如我們顯示映像的ImageView僅僅有200 X 200 像素,而我們的圖片有800 X 800 像素,那你把這麼大的一張圖放到這麼小的ImageView中,有啥用呢?白白浪費了記憶體。OK,那麼以下我們就來對映像進行壓縮,Options參數中給我們提供了這樣一個屬性——inSampleSize,這個屬效能夠設定映像的縮放比例,比如一張1000 X 1000像素的映像。設定inSampleSize為5。意思就是把這個映像縮放到了五分之中的一個。即200 X 200 。
OK,以下我們就通過這樣一個方法來對映像進行最佳化,首先,我們須要建立一個方法來擷取到一個合適的inSampleSize:
/** * 擷取合適的inSampleSize * @param options * @param targetWidth 期望Width * @param targetHeight 期望Height * @return */public static int getInSampleSize(BitmapFactory.Options options, int targetWidth, int targetHeight) { // 原始圖片的高度和寬度 final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > targetHeight || width > targetWidth) { // 計算出實際寬高和目標寬高的比率 final int heightRate = Math.round((float) height / (float) targetHeight); final int widthRate = Math.round((float) width / (float) targetWidth); inSampleSize = heightRate < widthRate ? heightRate : widthRate; } return inSampleSize;}
方法很easy。就是通到期望長寬來擷取縮放的比例。以下我們就建立一個方法來擷取縮放後的映像。這裡為了示範,我們僅僅建立從資源檔裡擷取映像的方法:
/** * 使用targetWidth、targetHeight來擷取合適的inSampleSize * 並使用inSampleSize來縮放得到合適大小的映像 * @param res getResources() * @param resId id * @param targetWidth * @param targetHeight * @return */public static Bitmap decodeSuitableBitmap(Resources res, int resId, int targetWidth, int targetHeight) { // 空手套白狼 final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); // 計算合適的inSampleSize options.inSampleSize = getInSampleSize(options, targetWidth, targetHeight); // 載入到記憶體 options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options);}
通過調用decodeSuitableBitmap這樣一個方法,我們就能夠很easy的將映像進行壓縮。
我的Github
我的視訊 慕課網
Android非同步載入全解析之大圖處理