*****
**圖片異步加載概述**
[TOC=6]
# 1. 什么是圖片的異步加載?
異步,在安卓開發中大家熟悉嗎?
熟悉。
說到異步大家能想到什么呢?
多線程開發,Thread、Handler、AsyncTask。
我們在哪里使用異步呢?
網絡請求數據。
圖片的異步加載就是在子線線程中獲取圖片然后在主線程中更新到界面上的操作。
今天我們做一個需求:加載URL中的圖片,顯示到ImageView上。
# 2. 為什么要進行圖片的二次采樣?

在Android應用里,最耗費內存的就是圖片資源。并且在Android系統中。讀取位圖Bitmap時,分給虛擬機中的圖片的堆棧大小僅僅有8M。假設超出了。就會出現OutOfMemory異常
~~~
E/AndroidRuntime(? 697): java.lang.OutOfMemoryError
E/AndroidRuntime(? 697): ?? ?at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
E/AndroidRuntime(? 697): ?? ?at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:500)
E/AndroidRuntime(? 697): ?? ?at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:353)
E/AndroidRuntime(? 697): ?? ?at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:376)
E/AndroidRuntime(? 697): ?? ?at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:406)
E/AndroidRuntime(? 697): ?? ?at com.example.imagetoshow2.ImageAdapter.createReflectedImages(ImageAdapter.java:66)
E/AndroidRuntime(? 697): ?? ?at com.example.imagetoshow2.ImageAdapter.getView(ImageAdapter.java:54)
E/AndroidRuntime(? 697): ?? ?at android.widget.AbsSpinner.onMeasure(AbsSpinner.java:193)
~~~
# 3. 了解一下關于Bitmap的Config
ARGB: A:透明度 R:紅色 G:綠 B:藍
~~~
public enum Config {
ALPHA_8 (1),
RGB_565 (3),
@Deprecated
ARGB_4444 (4),
ARGB_8888 (5);
}
~~~
Bitmap.Config ARGB\_4444:每個像素占用2byte內存 ,即A=4,R=4,G=4,B=4,那么一個像素點占4+4+4+4=16位
Bitmap.Config ARGB\_8888:每個像素占用4byte內存 ,即A=8,R=8,G=8,B=8,那么一個像素點占8+8+8+8=32位
Bitmap.Config RGB\_565:每個像素占用2byte內存,即R=5,G=6,B=5,沒有透明度,那么一個像素點占5+6+5=16位
Bitmap.Config ALPHA\_8:每個像素占用1byte內存,只有透明度,沒有顏色。 ?


?
# 4. 內存計算
1TB=1024GB 1GB=1024MB 1MB=1024KB 1KB=1024B 1B=8b
一張 1024 \* 1024 像素,采用ARGB8888格式,一個像素32位,每個像素就是4字節,占有內存就是4M若采用RGB565,一個像素16位,每個像素就是2字節,占有內存就是2M。
Glide加載圖片默認格式RGB565,Picasso為ARGB8888,默認情況下,Glide占用內存會比Picasso低,色彩不如Picasso鮮艷,自然清晰度就低。
通常我們優化Bitmap時,當需要做性能優化或者防止OOM(Out Of Memory),我們通常會使用Bitmap.Config.RGB\_565這個配置,因為Bitmap.Config.ALPHA\_8只有透明度,顯示一般圖片沒有意義,Bitmap.Config.ARGB\_4444顯示圖片不清楚,Bitmap.Config.ARGB\_8888占用內存最多。
圖片加載
如果我們想要加載一張大圖到內存中,如果不進行壓縮的話,那么很顯然就會出現OOM的崩潰,
# 5. 二次采樣原理分析
如何將一張大圖壓縮到100kb以下并且保持不失真的特性?這就需要用到下面這個類了**BitmapFactory.Options**
BitmapFactory.Options縮放圖片主要用到inSample采樣率,
inSample = 1,采樣后圖片的寬高為原始寬高
inSample > 1,例如2,**寬高均為原圖的寬高的1/2**
一個采用ARGB8888的1024 \*1024 的圖片
inSample = 1,占用內存就 1024 \*1024 \*4 = 4M
inSample = 2,占用內存就 512 \*512 \* 4 = 1M
BitmapFactory 給我們提供了一個解析圖片大小的參數類 BitmapFactory.Options ,把這個類的對象的 inJustDecodeBounds 參數設置為 true,這樣解析出來的 Bitmap 雖然是個 null,但是 options 中可以得到圖片的寬和高以及圖片的類型。得到了圖片實際的寬和高之后我們就可以進行壓縮設置了,主要是計算圖片的采樣率。
`
~~~
public class BitmapUtils {
/**
* @param filePath 要加載的圖片路徑
* @param destWidth 顯示圖片的控件寬度
* @param destHeight 顯示圖片的控件的高度
* @return
*/
public static Bitmap getBitmap(String filePath, int destWidth, int destHeight) {
//第一次采樣
BitmapFactory.Options options = new BitmapFactory.Options();
//該屬性設置為true只會加載圖片的邊框進來,并不會加載圖片具體的像素點
options.inJustDecodeBounds = true;
//第一次加載圖片,這時只會加載圖片的邊框進來,并不會加載圖片中的像素點
BitmapFactory.decodeFile(filePath, options);
//獲得原圖的寬和高
int outWidth = options.outWidth;
int outHeight = options.outHeight;
//定義縮放比例
int sampleSize = 1;
while (outHeight / sampleSize > destHeight || outWidth / sampleSize > destWidth) {
//如果寬高的任意一方的縮放比例沒有達到要求,都繼續增大縮放比例
//sampleSize應該為2的n次冪,如果給sampleSize設置的數字不是2的n次冪,那么系統會就近取值
sampleSize *= 2;
}
/********************************************************************************************/
//至此,第一次采樣已經結束,我們已經成功的計算出了sampleSize的大小
/********************************************************************************************/
//二次采樣開始
//二次采樣時我需要將圖片加載出來顯示,不能只加載圖片的框架,因此inJustDecodeBounds屬性要設置為false
options.inJustDecodeBounds = false;
//設置縮放比例
options.inSampleSize = sampleSize;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
//加載圖片并返回
return BitmapFactory.decodeFile(filePath, options);
}
}
~~~
`

跟上 學會了嗎?
- 咨詢項目實戰
- 第一單元 HTTP協議
- 1.1 OSI七層模型
- 1.2 HTTP協議(重點)
- 1.3 HTTPS協議(了解)
- 1.4 TCP/IP協議擴展
- 1.5 WebService簡介及實戰(無接口)
- 1.6 課后練習
- 第二單元 HTTPURLConnection
- 2.1 ANR
- 2.2 網絡判斷
- 2.3 HTTPURLConnection
- 2.4 課后練習
- 第三單元 AsyncTask
- 3.1 AsyncTask概述
- 3.2 AsyncTask基本使用
- 3.3 課后練習
- 第四單元 圖片異步加載
- 4.1 圖片異步加載概述
- 4.2 LruCache
- 4.3 DiskLRUCache
- 4.4 圖片三級緩存概述
- 4.5 封裝圖片加載緩存框架
- 第五單元 ListView多條目
- 5.1 ListView多條目概述
- 5.2 ListView多條目的使用
- 第六單元 ListView實現下拉刷新上拉加載
- 6.1 下拉刷新和上拉加載更多
- 6.2 XListView概述
- 6.3 XListView的使用
- 第七單元 封裝網絡框
- 7.1 封裝網絡框架概述
- 7.2 網絡框架的封裝
- 第八單元 項目介紹
- 8.1 公司項目團隊架構簡介
- 8.2 項目文檔及項目流程介紹
- 8.3 項目管理
- 8.4 項目開發
- 第九單元 項目框架搭建
- 9.1 基類封裝概述
- 9.2 Application中初始化配置
- 9.3 項目中的工具類
- 9.4 封裝網絡請求框架
- 9.5 封裝圖片異步緩存框架
- 第十單元 搭建UI框架1
- 10.1 側滑菜單概述
- 10.2 主界面框架搭建
- 第十一單元 搭建UI框架2
- 11.1 TabLayout的概述
- 11.2 TabLayout的使用
- 第十二單元 圖片上傳
- 12.1 圖片上傳概述
- 12.2 圖片上傳的實現
- 第十三單元 PullToRefresh
- 13.1 PullToRefresh概述
- 13.2 PullToRefresh的使用
- 13.3 緩存業務實現思路
- 第十四單元 事件分發及滑動沖突
- 14.1 事件分發概述
- 14.2 事件分發流程
- 14.3 事件分發的使用
- 第十五單元 傳感器的基本使用
- 15.1 傳感器概述
- 15.2 傳感器的使用
- 第十六單元 HTML與CSS復習
- 16.1 HTML
- 16.2 CSS
- 第十七單元 js復習
- 17.1 js基礎語法
- 17.2 js數組和內置對象
- 17.3 js常用事件
- 17.4 js對象模型
- 17.5 js 正則表達式
- 第十八單元 WebView
- 18.1 WebView 概述
- 18.2 WebView的使用
- 18.3 WebView與js交互
- 第十九單元 項目案例
- 項目概述
- 第二十單元 項目答辯
- 周考
- 第一周周考
- 第二周周考
- 第三種周考
- 月考
- 接口文檔