1,介绍
Android原生没有提供加载网络图片的方案
原理概述:图片加载的工作流(task flow)都是3级缓存的流程;图片的内存缓存一定是LruCache实现;图片下载和读取线程的调度一定是通过线程池管理
画图说明图片加载原理
第三方图片加载库
-
UniversalImageLoader:老牌优秀的图片加载类库,特点是配置项丰富,支持圆形图片效果显示以及添加图片加载动画。
-
Picasso : Square公司出品。也是很早期出现的图片加载库。默认加载图片不会压缩,并且图片渲染模式是ARGB_8888,占用内存相比Glide稍微高一点,但是可以指定图片加载的宽高,便会依据图片的宽高进行缩放。
-
Glide:专门为优化Picasso而生,所以API和Picasso简直一模一样。内部会自动根据图片的宽高来压缩图片,并且图片渲染模式为RGB_565,内存占用会减少一半,专门针对滑动中的图片加载有优化。和Picasso相比,推荐使用Glide。
-
Fresco : Facebook公司开源的。特点是在android4.4以及以下,将图片的放入Android native的C++内存中,而不是Java堆内存,所以占用的Java堆内存很小,大大减小了程序出现OOM的几率;支持WebP和Gif显示;支持多种图片的显示配置,比如圆形。
2,实现原理
-
请求,内存--请求本地--访问网络
3,图片框架通过SampleSize采样进行图片压缩
采样比,颜色模式进行图片压缩
【1】添加布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="250dp" />
<TextView
android:textColor="#000"
android:id="@+id/text"
android:textSize="20sp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
【2】找到控件计算。
-
把大图放在drawable-nodpi中 (布局分辨率适配)
1920* 1200, 默认8888 ,一个像素占4个byte 。
1920*1200*4 =byte /1024 = kb /1024/mb
-
找到控件
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_compress);
imageView = (ImageView) findViewById(R.id.image);
textView = (TextView) findViewById(R.id.text);
new Handler().postDelayed(
new Runnable() {
@Override
public void run() {
loadImage();
}
}, 100);
}
-
计算图片占用内存大小,RGB_565是默认为2个byte
private void loadImage() {
//1.先计算当前所用的内存
long preMemory = Runtime.getRuntime().totalMemory();
//2.加载图片
BitmapFactory.Options opts = new BitmapFactory.Options();
//只加载图片的宽高并不真正加载内容,此时返回的图片会是空的图片
opts.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.drawable.fast,opts);
//拿到了图片的宽高
int bmpW = opts.outWidth;
int bmpH = opts.outHeight;
//设置采样比例
opts.inSampleSize = findBestSampleSize(bmpW,bmpH);
//注意取消该标志
opts.inJustDecodeBounds = false;
//设置颜色的渲染模式进行压缩
opts.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.fast,opts);
imageView.setImageBitmap(bitmap);
long costMemory = Runtime.getRuntime().totalMemory() - preMemory;
textView.setText("图片占用内存:"+ Formatter.formatFileSize(this,costMemory));
}
-
计算sampleSize 的宽高比
/**
* 计算最好的采样比例大小
* @param bmpW
* @param bmpH
* @return
*/
private int findBestSampleSize(int bmpW, int bmpH) {
int sampleSize = 1;
//根据图片和ImageVIew 的宽高比例来算
float wRatio = bmpW/imageView.getWidth();
float hRatio = bmpH/imageView.getHeight();
sampleSize = (int) Math.max(wRatio,hRatio);
sampleSize = Math.max(1,sampleSize);
return sampleSize;
}