ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
***** **图片异步加载概述** [TOC=6] # 1. 什么是图片的异步加载? 异步,在安卓开发中大家熟悉吗? 熟悉。 说到异步大家能想到什么呢? 多线程开发,Thread、Handler、AsyncTask。 我们在哪里使用异步呢? 网络请求数据。 图片的异步加载就是在子线线程中获取图片然后在主线程中更新到界面上的操作。 今天我们做一个需求:加载URL中的图片,显示到ImageView上。 # 2. 为什么要进行图片的二次采样? ![](https://box.kancloud.cn/a65bc06ea363c75904e84c207f733bab_240x427.jpg) 在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内存,只有透明度,没有颜色。   ![](https://box.kancloud.cn/9a92c75f0d552dd04656ca0fadb99b28_1174x1566.png) ![](https://box.kancloud.cn/be9064158032910b55ee4fa26ba978ed_1024x1365.jpg)   # 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); } } ~~~ ` ![](https://box.kancloud.cn/3776ee2322c00dd39b896440206185a8_700x466.jpg) 跟上 学会了吗?