加载大图怎么避免溢出实际做法就是对图像进行压缩,也是比较老的话题了,在最初做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上了,来看一下它的描述:

下面运行看下效果:

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

Android加载大图到内存如何避免内存溢出?的更多相关文章

  1. Android 加载大图

    在 Android 开发中, Bitmap 是个吃内存大户,稍微操作不当就会 OOM .虽然现在第三方的图片加载库已经很多,很完善,但是作为一个 Androider 还得知道如何自己进行操作来加载大图 ...

  2. android加载大图,防止oom

    高效加载大图片 我们在编写Android程序的时候经常要用到许多图片,不同图片总是会有不同的形状.不同的大小,但在大多数情况下,这些图片都会大于我们程序所需要的大小.比如说系统图片库里展示的图片大都是 ...

  3. Android加载大图不OOM

    首先,我们试着往sdcard里放一张400k的图片,但是分辨率是2560*1600 布局简单 <?xml version="1.0" encoding="utf-8 ...

  4. Android高效加载大图、多图解决方案,有效避免程序内存溢出现象

    好久没有写博客了,今天就先写一个小的关于在Android中加载大图如何避免内存溢出的问题. 后面会写如何使用缓存技术的核心类,android.support.v4.util.LruCache来加载图片 ...

  5. Android学习笔记_51_转android 加载大图片防止内存溢出

    首先来还原一下堆内存溢出的错误.首先在SD卡上放一张照片,分辨率为(3776 X 2520),大小为3.88MB,是我自己用相机拍的一张照片.应用的布局很简单,一个Button一个ImageView, ...

  6. Android中高效的显示图片之一 ——加载大图

    在网上看了不少文章,发现还是官方文档介绍最详细,把重要的东西简单摘要出来.详细可看官方文档地址 ( http://www.bangchui.org/read.php?tid=9 ) . 在应用中显示图 ...

  7. 解决MWPhotoBrowser中的SDWebImage加载大图导致的内存警告问题

    下面两种现象,用同一种方法解决 1.解决MWPhotoBrowser中的SDWebImage加载大图导致的内存警告问题 2.突然有一天首页访问图片很慢,至少隔20多秒所有图片才会出来.(解析:app使 ...

  8. android加载大量图片内存溢出的三种方法

    android加载大量图片内存溢出的三种解决办法 方法一:  在从网络或本地加载图片的时候,只加载缩略图. /** * 按照路径加载图片 * @param path 图片资源的存放路径 * @para ...

  9. android加载字体内存泄漏的处理方法

    在开发android app的开发过程中,会使用到外部的一些字体.外部字体在加载的时候,容易造成内存泄漏. 比如: Typeface tf=Typeface.createFromAsset(getAs ...

随机推荐

  1. 你应该知道的4个DSP开发支持库

    引言 在dsp开发中,为了节省开发时间和难度,TI将一些成熟的算法封装为模块,供开发者使用.如果能充分利用这些算法支持库,对于加快dsp开发进程与提高代码质量.稳定性有非常大的帮助. Digital ...

  2. LeetCode 783. 二叉搜索树结点最小距离(Minimum Distance Between BST Nodes)

    783. 二叉搜索树结点最小距离 LeetCode783. Minimum Distance Between BST Nodes 题目描述 给定一个二叉搜索树的根结点 root, 返回树中任意两节点的 ...

  3. 022 Android .9图片的含义及制作教程

    1.图片(.9.png格式)的概念 (1)9patch图片是andriod app开发里一种特殊的图片形式,文件的扩展名为:.9.png (2)9patch图片的作用就是在图片拉伸的时候保证其不会失真 ...

  4. 《Mysql - 幻读》

    一:准备 - 为了深入了解幻读,准备数据. CREATE TABLE `t` ( `id` ) NOT NULL, `c` ) DEFAULT NULL, `d` ) DEFAULT NULL, PR ...

  5. 使用mybatis完成增删改查

    插入 插入数据 <insert id="insertUser2" parameterType="UserEntity"> insert into u ...

  6. (一)构建基于ubuntu docker MySQL 5.6 镜像并推送到Docker Hub

    一,创建目录二,文件准备三,构建四,使用五,在宿主机上连接docker 中的mysql六,推送镜像到Docker hub 一,创建目录 mkdir -p mysql/5.6 二,文件准备 注意执行脚本 ...

  7. 玫瑰花小制作分享-JavaScript(七夕专属浪漫)

    分享一个玫瑰花的制作小方法,用小小的代码给自己的她送上一个不一样的玫瑰花. 玫瑰花代码由JavaScript实现,JavaScript 作为一种脚本语言, 被发明用于在 HTML 网页上使用,可以给H ...

  8. PAT(B) 1049 数列的片段和(C)规律

    题目链接:1049 数列的片段和 (20 point(s)) 题目描述 给定一个正数数列,我们可以从中截取任意的连续的几个数,称为片段.例如,给定数列 { 0.1, 0.2, 0.3, 0.4 },我 ...

  9. C语言处理字符串

    1. strtok 函数原型: char * strtok(char *str, const char * delim); 注意点: 两个入参必须为字符串数组: 第一次调用要传str, delim,后 ...

  10. JS ES6中export和import详解

    1.Export 模块是独立的文件,该文件内部的所有的变量外部都无法获取.如果希望获取某个变量,必须通过export输出, // profile.js export var firstName = ' ...