1. 内存管理基础知识

http://www.cnblogs.com/xingfuzzhd/p/3485924.html

  • 1. mImageView.setImageResource(R.drawable.my_image); 这段代码会调用 BitmapFactory.decodeStream() 生成一个 Bitmap。所以不要以为它比自己创建 Bitmap 节省内存。

3.  实际测试:

我使用了多种调用图片的方法来测试:

第一种:

// 直接载入资源 id
ImageView image = (ImageView) findViewById(R.id.imageView1)

第二种:

创建一个函数,根据 id 载入图片。杀死 Activity 时回收 Bitmap

public BitmapDrawable getImageBitmap(int idImage) {
  Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), idImage);
  images.add(bitmap);
  return new BitmapDrawable(context.getResources(), bitmap);
}

第三种:

创建一个类

/**
* solution for OOM ------> compress bitmap
*/
public class BitmapUtils {
private static final String TAG = "BitmapUtils";
/**
* calulate the compress rate
*/
private static int calculateInSampleSize(BitmapFactory.Options opts,int reqHeight,int reqWidth) {
if(opts == null) {
return -1;
}
int width = opts.outWidth;
int height = opts.outHeight; int sampleSize = 1; if(width > reqWidth || height > reqHeight) {
int heightRatio = (int) (height/(float)reqHeight);
int widthRatio = (int) (width/(float)reqWidth);
sampleSize = (heightRatio > widthRatio) ? widthRatio : heightRatio;
}
return sampleSize;
} /**
* compress an image refer to the goal dimension
* @param res
* @param resId
* @param reqWidth
* @param reqHeight
* @return Bitmap
*/
public static Bitmap decodeSampledBitmapFromResource(Resources res,int resId,int reqWidth,int reqHeight) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, opts);
int sampleSize = calculateInSampleSize(opts, reqHeight, reqWidth);
Log.i(TAG,"before[width:"+opts.outWidth+",height:"+opts.outHeight+"]");
opts.inJustDecodeBounds = false;
opts.inSampleSize = sampleSize;
/* newly added */
opts.inPreferredConfig = Bitmap.Config.RGB_565;
opts.inPurgeable = true;
opts.inInputShareable = true;
/* newly added */
Log.i(TAG,"insamplesize="+sampleSize);
Bitmap bitmap = BitmapFactory.decodeResource(res, resId, opts);
Log.i(TAG,"after[width:"+bitmap.getWidth()+",height:"+bitmap.getHeight()+"]");
return bitmap;
} /**
* compress an image refer to the goal dimension
*
* @param data image byte array
* @param reqWidth
* @param reqHeight
* @return
*/
public static Bitmap decodeSampledBitmapFromByteArray(byte[] data,int reqWidth,int reqHeight) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(data, 0, data.length, opts);
Log.i(TAG,"before[width:"+opts.outWidth+",height:"+opts.outHeight+"]");
opts.inSampleSize = calculateInSampleSize(opts, reqHeight, reqWidth);
Log.i(TAG,"insamplesize="+opts.inSampleSize);
opts.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opts);
Log.i(TAG,"after[width:"+bitmap.getWidth()+",height:"+bitmap.getHeight()+"]");
return bitmap;
} public static Bitmap decodeResourceWithLowMemory(Context context, int resId) {
BitmapFactory.Options opt = new BitmapFactory.Options();
// Bitmap.Config.ALPHA_8,Bitmap.Config.ARGB_4444,Bitmap.Config.RGB_565
// 设置这几个参数效果都差不多,确实相当省内存啊,而且还跟原图清晰度相当
opt.inPreferredConfig = Bitmap.Config.RGB_565;
opt.inPurgeable = true;
opt.inInputShareable = true;
return BitmapFactory.decodeResource(context.getResources(), resId, opt);
} public static Bitmap loadToImageViewFromResource(Resources res,int resId,ImageView imageView) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, opts);
int reqHeight = imageView.getLayoutParams().height;
int reqWidth = imageView.getLayoutParams().width;
int sampleSize = calculateInSampleSize(opts, reqHeight, reqWidth);
Log.i(TAG,"before[width:"+opts.outWidth+",height:"+opts.outHeight+"]");
opts.inJustDecodeBounds = false;
opts.inSampleSize = sampleSize;
/* newly added */
opts.inPreferredConfig = Bitmap.Config.RGB_565;
opts.inPurgeable = true;
opts.inInputShareable = true;
/* newly added */
Log.i(TAG,"insamplesize="+sampleSize);
Bitmap bitmap = BitmapFactory.decodeResource(res, resId, opts);
Log.i(TAG,"after[width:"+bitmap.getWidth()+",height:"+bitmap.getHeight()+"]");
return bitmap;
} }

4. 测试过程:

创建两个 Activity,每个都载入几个大图片,然后两个 Activity 之间不停的切换。

第一种方法,切换多次后 OOM (out of memory)。 第二种方法,更快的 OOM。

第三种,如果压缩率够高的话,几乎不会 OOM。比如原始图片为 2048 * 1600,然后目标 ImageView 的大小为 200* 150。最后内存消耗将大大减小。然后如果

两者分辨率差距不大,最后内存消耗将不会被优化,最后也将 OOM。

5. 原理

通常,我们使用BitmapFactory.decodeResource()方法来从资源文件中读取一张 图片并生成一个 Bitmap。但如果使用一个BitmapFactory.Options对象,并把该对象的inJustDecodeBounds属性设 置为true,decodeResource()方法就不会生成 Bitmap 对象,而仅仅是读取该图片的尺寸和类型信息。所以在前面的类的一些方法中,我们用 BitmapFactory decode了两次图片,但第一次只是获取信息而没有生成 Bitmap 对象,所以没有未回收的 Bitmap 出现。

6. 一些推荐的解决方案

弱引用,LruCache,或者开源项目 :Android-Universal-Image-Loader

延伸:一个Bitmap到底占用多大内存?系统给每个应用程序分配多大内存?

· Bitmap占用的内存为:像素总数 * 每个像素占用的内存。在Android中,Bitmap有四种像素类型:ARGB_8888、ARGB_4444、ARGB_565、ALPHA_8,他 们每个像素占用的字节数分别为4、2、2、1。因此,一个2000*1000的ARGB_8888类型的Bitmap占用的内存为 2000*1000*4=8000000B=8MB。

· Android根据设备屏幕尺寸和dpi的不同,给系统分配的单应用程序内存大小也不同,具体如下表(表格取自Android 4.4 Compatibility Definition Document (CDD)):

屏幕尺寸  DPI  应用内存
 small / normal / large  ldpi / mdpi  16MB
 small / normal / large  tvdpi / hdpi  32MB
 small / normal / large  xhdpi  64MB
 small / normal / large  400dpi  96MB
 small / normal / large  xxhdpi  128MB
 xlarge  mdpi  32MB
 xlarge  tvdpi / hdpi  64MB
 xlarge  xhdpi  128MB
 xlarge  400dpi  192MB
 xlarge  xxhdpi  256MB

Android 内存管理研究的更多相关文章

  1. Android内存管理机制之一:low memory killer

    转载自http://www.miui.com/thread-29268-1-1.html 准备写这个专题之前,心里是有点忐忑的.首先Android内存管理机制相当复杂,想要讲清楚比较困难:其次对于绝大 ...

  2. Android 内存管理分析(四)

    尊重原创作者,转载请注明出处: http://blog.csdn.net/gemmem/article/details/8920039 最近在网上看了不少Android内存管理方面的博文,但是文章大多 ...

  3. 移动端测试===Android内存管理: 理解App的PSS

    Android内存管理: 理解App的PSS 原文链接:http://www.littleeye.co/blog/2013/06/11/android-memory-management-unders ...

  4. 浅谈Android内存管理

    最近在网上看了不少Android内存管理方面的博文,但是文章大多都是就单个方面去介绍内存管理,没有能全局把握,缺乏系统性阐述,而且有些观点有误,仅仅知道这些,还是无法从整体上理解内存管理,对培养系统优 ...

  5. [Android Memory] Android内存管理、监测剖析

    转载自:http://blog.csdn.net/anlegor/article/details/23398785 Android内存管理机制: Android内存管理主要有:LowMemory Ki ...

  6. Android——内存管理基础

    内存收集概念 内存垃圾收集器(garbage collector) 概念:自定内存管理. 功能:分配内存.保证所有被引用的对象还在内存中.可以释放在运行的代码中不再引用的对象的内存. 垃圾收集器避免了 ...

  7. Android内存管理

    首先Android理机制相当复杂.想要讲清楚比較困难.其次对于绝大多数用户来说.仅仅关心内存够不够用,至于内存怎样管理的这样的技术细节,不是用户须要去考虑的,写这样一个专题有没有意义?毕竟我们是用手机 ...

  8. Android 内存管理 &Memory Leak & OOM 分析

    转载博客:http://blog.csdn.net/vshuang/article/details/39647167 1.Android 进程管理&内存 Android主要应用在嵌入式设备当中 ...

  9. 【原创】Android内存管理-OnTrimMemory

    Application中有两个与内存管理相关的方法:onLowMemory()和 onTrimMemory(int level),源码如下 @CallSuper public void onLowMe ...

随机推荐

  1. Spring集成的Quartz 并发

    以前经常在任务调度程序中使用Spring集成的Quartz,这种方式可以用简单的声明式配置即可实现定时任务,并结合了Spring自身的Bean的管理功能,非常方便.配置样本如下: <bean i ...

  2. 【转】Unity Scene场景自定义坐标轴

    来自:https://blog.csdn.net/cheng624/article/details/70859054 多看看别人的代码是没有坏处的,即使学不了人家的大框架,偶尔拾起一些小东西也是可以的 ...

  3. AUC,KS,ROC

    要弄明白ks值和auc值的关系首先要弄懂roc曲线和ks曲线是怎么画出来的.其实从某个角度上来讲ROC曲线和KS曲线是一回事,只是横纵坐标的取法不同而已.拿逻辑回归举例,模型训练完成之后每个样本都会得 ...

  4. idea git 操作

    工作中多人使用版本控制软件协作开发,常见的应用场景归纳如下: 假设小组中有两个人,组长小张,组员小袁 场景一:小张创建项目并提交到远程Git仓库 场景二:小袁从远程Git仓库上获取项目源码 场景三:小 ...

  5. python将url转换成二维码

    准备环境 python生成二维码,需要依赖包qrcode和PIL(二维码的实质就是一个url.) python3安装PIL:pip install PIL python2安装PIL:pip insta ...

  6. 学习 java 编程语言两个月来的感受

    今天是我接触java编程的第81天, 现在的感受是觉得非常快乐, 每次看着自己的写的代码能成功运行的时候那种喜悦是无法言表的, 最初接触电脑还是在小学, 后来到了初中觉得电脑无非就是点点鼠标, 按按键 ...

  7. 05-了解activiti目录结构

    数据库底层支持的23张表的增删改查 如果你不会用activiti的API,可以看一下开发文档 流程引擎ProcessEngines,最重要是这个玩意. libs就更重要了,我们使用一个框架主要是使用它 ...

  8. Get The Client Info From PHP SERVER Arrary

    Get The Client Info From PHP SERVER Arrary <?php date_default_timezone_set( "Asiz/Shanghai&q ...

  9. JavaScript Math.floor() 方法

    定义和用法: floor() 方法可对一个数进行下舍入. 语法: Math.floor(x); x:必须参数,可以是任意数值或表达式: 返回值: 小于等于 x,且与 x 最接近的整数. 说明: flo ...

  10. webform版部分视图与请求拦截

    .主控前台页面 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebFor ...