当前位置: 首页 > 知识库问答 >
问题:

试图阻止OutOfMemoryError查看MAT-Android

赵元白
2023-03-14

我正在尝试防止我的android应用程序中出现OutOfMemoryError。我读过很多帖子,但我还不能解决它。

该应用程序有背景活动,所以我认为这是主要问题。OutOfMemoryError仅在某些设备中发生(可能是由于VM堆),我需要确保此错误不会在任何设备中产生崩溃。

我最近读了关于MAT(内存分析插件),我在应用程序运行时执行了它,在这里你可以看到结果:

支配树

汇报

在这项活动中,我对每个方向(家、家和土地)都有一个背景。两个大小都相同(190kb,jpg)。当我创建HPROF文件时,活动是横向的,我以前没有运行过纵向的。为了达到目的,我可以从这个结果中得出什么结论?

如果有必要我可以补充更多信息

编辑

为了避免OutOfMemoryError,我尝试使用此页面的方法,但我无法获得它。这是我的密码:

decodeFromResource类

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;

public class decodeFromResource {

    public static int calculateInSampleSize(BitmapFactory.Options options,
            int reqWidth, int reqHeight) {

        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            // Calculate the largest inSampleSize value that is a power of 2 and
            // keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) > reqHeight
                    && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }
        }

        return inSampleSize;
    }

    public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
            int reqWidth, int reqHeight) {

        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeResource(res, resId, options);
    }

    public static Drawable getDecodedDrawableFromResource(Resources res, int resId,
            int reqWidth, int reqHeight){
        return new BitmapDrawable(res, decodeSampledBitmapFromResource(res, resId, reqWidth, reqHeight));
    }
}

来自主活动的onCreate方法

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.home);

        resources = getResources();
        DisplayMetrics metrics = resources.getDisplayMetrics();

        layoutHome = (LinearLayout) findViewById(R.id.home_layout);
        if (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
            layoutHome.setBackgroundDrawable(decodeFromResource
                    .getDecodedDrawableFromResource(resources, R.drawable.home,
                            metrics.widthPixels, metrics.heightPixels));
        } else {
            layoutHome.setBackgroundDrawable(decodeFromResource
                    .getDecodedDrawableFromResource(resources,
                            R.drawable.home_land, metrics.heightPixels,
                            metrics.widthPixels));
        }

我只在后台实现了“高效加载大位图”的方法,因为除此之外,我只有五个非常小的按钮。我是否也需要为他们实现该方法?你能看到任何错误吗?

共有3个答案

伊锦
2023-03-14
options.inPurgeable = true;
options.inInputShareable = true;

这些标志允许在内存压力下丢弃与位图对象关联的实际位,并在您仍在使用位图时透明地重新解码。

云育
2023-03-14

尝试使用Android: largeHeap="true"标签在你的Androidanifest.xml这应该确保Android将处理更大的位图。

编辑

我必须指出,这不是问题的最终解决方案,它不会阻止OutOfMemory异常,但它们不太可能出现。也许吉拉德·海莫夫提出了解决这个问题的正确方法

夏昌胤
2023-03-14

您可能正在按原样加载jpg文件,这很容易导致内存不足,即使在功能强大的设备上也是如此。

请记住,加载到内存中的图像没有压缩,在大多数设备上,单个像素由4个内存字节表示。例如,一个7 MPixel的图像需要28兆字节的内存块,这可能会使你的应用程序真正接近OutOfMemory崩溃。

解决方案很简单:始终根据应用程序的需要加载缩小的图像。

要做到这一点,请从读取图像大小开始:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;

上面的代码不会加载实际的图像文件。它只会询问它的尺寸。

一旦你有了定义,你就可以计算用于加载缩放图像的“样本大小”。N的样本大小将导致加载1/(N*N)的原始图像像素,例如对于4的样本大小,仅加载1/16的图像像素。

最后加载缩小的图像:

final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);

options.inSampleSize = mySampleSize; //<-----------------------

options.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeResource(res, resId, options);

即使在执行按比例缩小的加载时,也最好使用try{...}捕获(OutOfstore)子句来保护代码,并允许优雅地处理加载失败。

详情如下:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

 类似资料:
  • 问题内容: 我有一个自定义的JDialog,当我的SwingWorker线程启动时会弹出。该对话框只有一个JProgressbar和一个Button(取消按钮)。我试图弄清楚如何取消我的SwingWorker,但是没有运气。我想我走对了。我编写了一个cancel方法,现在我只需要弄清楚按下按钮时如何调用它。代码如下… 问题答案: 您的取消按钮应调用该方法 在您的工作人员中,必须确保检查取消标志 请

  • 指定文档设置选项 可以随时更改文档的默认设置选项,如度量单位、透明度网格显示、背景颜色和文字设置(例如,语言、引号样式、上标和下标大小、出血以及可导出性)。单击 “编辑画板 ”按钮可关闭此对话框并激活画板工具。 1选择 “文件 ”>“文档设置 ”或单击 “控制 ”面板中的 “文档设置 ”按钮。(当未选择任何内容时,此按钮可用。) 2根据需要指定选项。 3如果要编辑画板,请单击 “编辑画板 ”进入画

  • 问题内容: 我对Go如何处理非阻塞IO感到困惑。API在我看来基本上是同步的,并且在Go上观看演示时,听到诸如“和调用块”之类的注释并不罕见。 从文件或网络读取时,Go是否使用阻塞IO?还是当在Go Routine中使用某种魔术来重写代码? 来自C#背景,这感觉非常不直观,在C#中,当使用异步API时我们使用了关键字。这清楚地表明,API可以产生当前线程,并在以后的延续中继续。 因此,TLDR;当

  • 主要内容:查看视图的字段信息,查看视图的详细信息,拓展阅读创建好视图后,可以通过查看视图的语句来查看视图的字段信息以及详细信息。本节主要讲解如何使用 SQL 语句来查看视图的字段信息以及详细信息。 查看视图的字段信息 查看视图的字段信息与查看数据表的字段信息一样,都是使用 DESCRIBE 关键字来查看的。具体语法如下: DESCRIBE 视图名; 或简写成: DESC 视图名; 示例 1 下面创建学生信息表 studentinfo 的一个视图,用于查询

  • 我有下面的屏幕(图像),当按下按钮时,它会显示一个侧菜单。菜单会出现,另外我还有一个uitableview来显示其他内容 我的问题是,当侧菜单出现时,uitableview的大小会调整。 我如何保持我的uitableview完整?我一直在尝试下一个,但我没有得到任何东西:

  • 在我的Espresso测试执行和AlertDialog会被提示并等待用户响应。Espresso测试只有在我按下“Accept”按钮但我想测试代替用户执行此事件时才会继续。 我注意到我的线程选项卡上有以下状态