加载大图怎么避免溢出实际做法就是对图像进行压缩,也是比较老的话题了,在最初做android时是经常会遇到的问题,而如今对于图片加载这一块都已经有很成熟稳定的三方库来弄它了,所以图片加载过大内存溢出的比较少了,倒是内存泄露还是经常出现,这次来用点时间来将这个问题给研究总结下。

android中每个app是有最大内存上限的,在新建模拟器的时候,有这样一个选项:

所以如果超过这个大小,则会内存溢出,所以下面准备一张大图,先直接加载到内存看是否溢出,之后再来解决溢出的情况:

接下来将这个图片显示在手机上,为了更好的说明问题,这里用模拟器来实验,该模拟器的vm heap等于16,其程序就是点击加载该图片:

activity_main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" > <Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="load" /> <ImageView
android:id="@+id/imageview"
android:layout_width="match_parent"
android:layout_height="match_parent" /> </LinearLayout>

MainActivity.java:

public class MainActivity extends Activity implements OnClickListener {

    private Button button;
private ImageView imgview; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
imgview = (ImageView) findViewById(R.id.imageview);
button.setOnClickListener(this);
} @Override
public void onClick(View arg0) {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.test);
imgview.setImageBitmap(bitmap);
} }

运行看效果:

很好的结果出现了:

在正式解决内存溢出之前,先来说明一下图片加载到内存大小的简单计算方式,我们看到的图片在硬盘上的大小是:

而加载到内存的大小是:

其实图片加载到内存所需的大小跟它文件本身大小没有关系,而是跟分辨率有关,这个图片的分辨率为:

而用画图软件将该图打开:

而一点像素点用RGB来表示,则需要3个字节表示:

所以可以简单算出这张图片占多少内存:

(2816x2112x3)byte=17842176byte=17MB,颜色有可能还有透明度,所以一个点肯定是多于3个字节,所以实际内存要得更多。

清楚了为什么溢出之后,下面来将这张图放到模拟器上,用图库来查看:

可见是有办法来避勉溢出的,那就是对图片进行缩放,下面来研究下图库缩放的原理:

接下来按照这个原理来对图片进行缩放:

首先要获取图片真实的宽高,而宽高是需要加载到内存才知道的,而目前图片加载到内存会溢出,那有办法获取么,当然有:

运行到模拟器上看效果:

其中最关键的就是options.inJustDecodeBounds选项的作用,查看一下它的说明:

其实它的原理就像在windows中点击图片文件时就知道它的一些图片信息:

而其实这些信息都是保存在头文件中的,用十六进制方式来打开该文件:

可以看到相印的一些信息,其原理就是这样。

接下来就要获取屏幕的宽高:

接下来则计算缩放比:

接下来再按照这个缩放比来进行缩放:

public class MainActivity extends Activity implements OnClickListener {

    private Button button;
private ImageView imgview; private int screenWidth;
private int screenHeight; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
imgview = (ImageView) findViewById(R.id.imageview);
button.setOnClickListener(this);
// 得到手机屏幕的宽高
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
screenHeight = windowManager.getDefaultDisplay().getHeight();
screenWidth = windowManager.getDefaultDisplay().getWidth();
Log.d("cexo", "屏幕宽:" + screenWidth + ";屏幕高:" + screenHeight);
} @Override
public void onClick(View arg0) {
BitmapFactory.Options options = new Options();
options.inJustDecodeBounds = true; Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.test, options); int imgHeight = options.outHeight;
int imgWidth = options.outWidth; Log.d("cexo", "图片宽:" + imgWidth);
Log.d("cexo", "图片高:" + imgHeight); // 计算缩放比例
int scaleX = imgWidth / screenWidth;
int scaleY = imgHeight / screenHeight;
int scale = 1;
if (scaleX > scaleY && scaleX >= 1) {
scale = scaleX;
}
if (scaleY > scaleX && scaleY >= 1) {
scale = scaleY;
} // 真的解析图片
options.inJustDecodeBounds = false;
options.inSampleSize = scale;
// 再次获得缩放之后的bitmap对象
bitmap =
BitmapFactory.decodeResource(getResources(), R.drawable.test,
options); imgview.setImageBitmap(bitmap);

} }

其中由于要真正解析图片了,所以需要将inJustDecodeBounds还原,另外缩放比被设置到options.inSampleSize上了,来看一下它的描述:

下面运行看下效果:

以上就是对加载大图片会溢出的解决方案的研究,不难,但值得学习。

最新文章

  1. Xamarin.Android-用ZXing实现二维码扫描以及连续扫描
  2. Opencv算法学习二
  3. MVC学习笔记1
  4. IOS开发-UIBarButtonItem系统自带图标总结
  5. linux-insides-cn-BOOK
  6. 利用系统镜像文件安装.Net框架的方式
  7. IE6下不能定义1px高度的容器和IE6 双边距
  8. cocos2dx进阶学习之CCBI文件
  9. JAVA之成员变量初始化
  10. jquery.form.js用法之清空form的方法
  11. leetcode先刷_Unique Binary Search Trees II
  12. NuGet包断线续传下载
  13. 运行SSIS包的六种方式
  14. 自定义QGraphicsItem
  15. 贝叶斯公式由浅入深大讲解—AI基础算法入门
  16. 中文乱码 URLEncode之后,后台获取仍是乱码问题详解
  17. SCSS 使用@each 方法循环遍历数组颜色并给li赋值
  18. WPF宝典Url
  19. Gradle 中 buildConfigField的巧妙应用
  20. maven项目出现红色感叹号报错

热门文章

  1. Spring切面编程AOP
  2. java查询图片显示无图片显示项目默认图片
  3. 2019年广东省赛gdccpc回顾
  4. jupyter notebook选择conda环境
  5. [.Net] - 使用 iTextSharp 生成基于模板的 PDF,生成新文件并保留表单域
  6. SAS学习笔记56 ODS ESCAPECHAR
  7. Fiddler抓取https原理
  8. 第2章 NIO入门
  9. 使用Dockerfile构建镜像并push到私有仓库
  10. Android Studio 生成 keystore 签名文件