jjzjj

android - 试图防止 OutOfMemoryError 看到 MAT - Android

coder 2023-12-29 原文

我试图在我的 Android 应用程序中防止 OutOfMemoryError。我已经阅读了很多帖子,但我仍然无法解决。

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

我最近阅读了有关 MAT(内存分析插件)的信息,并在应用程序运行时执行了它,在这里您可以看到结果:

支配树

报告

在这个 Activity 中,我有每个方向的背景(home,home_land)。两种尺寸相同(190kb,jpg)。当我创建 HPROF 文件时, Activity 是横向的,我之前没有运行过纵向。为了达到我的目的,我可以从这个结果中得出什么结论?

如果有必要,我可以添加更多信息

编辑

我尝试使用this page的方法为了也避免 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));
    }
}

主 Activity 的 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));
        }

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

最佳答案

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

请记住,加载到内存中的图像没有经过压缩,并且在大多数设备上,单个像素由 4 个内存字节表示。例如,一张 7 MPixel 的图像将需要 28 MByte 的内存块,这可能会使您的应用程序真正接近 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 {...} catch(OutOfmemory) 子句并允许优雅地处理加载失败。

此处有更多详细信息:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

关于android - 试图防止 OutOfMemoryError 看到 MAT - Android,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24471010/

有关android - 试图防止 OutOfMemoryError 看到 MAT - Android的更多相关文章

  1. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  2. ruby-on-rails - 您希望看到哪些 Rails 插件? - 2

    您认为可以作为插件很好地存在于您的Rails应用程序中必须实现的哪些行为?您过去曾搜索过哪些插件功能但找不到?哪些现有的Rails插件可以改进或扩展,如何改进或扩展? 最佳答案 我希望在管理界面中看到一个引擎插件,它提供了应用程序中所有模型的仪表板摘要,以及可配置的事件图表。 关于ruby-on-rails-您希望看到哪些Rails插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questio

  3. ruby-on-rails - Rails 3.2 防止使用错误保存对象 - 2

    我有一个ActiveRecord对象,我想在不对模型进行永久验证的情况下阻止它被保存。您过去可以使用errors.add执行类似的操作,但它看起来不再有效了。user=User.lastuser.errors.add:name,"namedoesn'trhymewithorange"user.valid?#=>trueuser.save#=>true或user=User.lastuser.errors.add:base,"myuniqueerror"user.valid?#=>trueuser.save#=>true如何在不修改用户对象模型的情况下防止将用户对象保存在Rails3.2中

  4. ruby - 防止SQL注入(inject)/好的Ruby方法 - 2

    Ruby中防止SQL注入(inject)的好方法是什么? 最佳答案 直接使用ruby?使用准备好的语句:require'mysql'db=Mysql.new('localhost','user','password','database')statement=db.prepare"SELECT*FROMtableWHEREfield=?"statement.execute'value'statement.fetchstatement.close 关于ruby-防止SQL注入(inject

  5. ruby - Ruby gems 的问题(损坏?)试图让指南针在 npm 中工作 - 2

    我不是Ruby专家,但想弄清楚发生了什么,因为我试图让指南针在节点应用程序中工作,但我的Ruby似乎坏了。打字:ruby--version让我:ruby2.1.1p76(2014-02-24revision45161)[x86_64-darwin13.0]我安装了Homebrew,之前遇到过Ruby版本的问题,但它似乎已安装并且可以正常工作。但是,当我使用gem输入请求时,出现此错误:$gem-hErrorloadingRubyGemsplugin"/Users/user_dir/.rvm/gems/ruby-2.1.1@global/gems/executable-hooks-1.3

  6. ruby-on-rails - 如何防止错误 "code converter not found (UTF-8)"? - 2

    我在生产环境(CentOS5.6)中遇到此错误,但在开发环境(Ubuntu11.04)中运行良好。在这两种环境中,该应用程序都使用Ruby1.9.3和Rails3.0.9,并由passenger和nginx提供服务。我的Mechanizegem版本是2.3。未找到代码转换器(UTF-8)此代码的最后一行触发它:mech=Mechanize.newpage=mech.get("http://myurl.com/login.php?login_name=a&password=b")form=page.form_with(:name=>"loginForm")form.field_with(

  7. ruby-on-rails - Rails 3 ActiveAdmin CanCan。如何设置用户只能看到属于他的记录? - 2

    我设置了属于客户类别的admin_users(客户是一家公司)。所以Customer有很多admin_users。我正在尝试限制对属于特定客户的装运记录的访问。我不希望客户看到其他客户的数据。所以我设置了它,但它似乎什么也没做......类(class)能力包括CanCan::Abilitydefinitialize(user)user||=AdminUser.newifuser.role=="administrator"can:manage,:allelsecannot:create,:allcannot:update,:allcannot:destroy,:allcan:read,

  8. ruby - 为什么我会看到这两个几乎相同的 Ruby 正则表达式模式的不同结果,为什么一个匹配我认为不应该匹配的内容? - 2

    使用Ruby1.9.2,我在IRB中有以下Ruby代码:>r1=/^(?=.*[\d])(?=.*[\W]).{8,20}$/i>r2=/^(?=.*\d)(?=.*\W).{8,20}$/i>a=["password","1password","password1","pass1word","password1"]>a.each{|p|puts"r1:#{r1.match(p)?"+":"-"}\"#{p}\"".ljust(25)+"r2:#{r2.match(p)?"+":"-"}\"#{p}\""}这会产生以下输出:r1:-"password"r2:-"password"r1:

  9. ruby - 为什么 split (' ' ) 试图变得(太)聪明? - 2

    我刚刚发现String#split有以下奇怪的行为:"a\tbc\nd".split=>["a","b","c","d"]"a\tbc\nd".split('')=>["a","b","c","d"]"a\tbc\nd".split(//)=>["a\tb","c\nd"]Thesource(来自2.0.0的string.c)超过200行,包含这样一段话:/*L5909*/elseif(rb_enc_asciicompat(enc2)==1){if(RSTRING_LEN(spat)==1&&RSTRING_PTR(spat)[0]==''){split_type=awk;}}后来,在

  10. ruby-on-rails - 试图在 gem 中要求 active_support - 2

    我有一个ruby​​gem,我想在包含在railsactive_support模块中的gem中使用Hash.from_xml方法。我的gemspec中有以下代码:gem.add_dependency'active_support','~>3.0.0'但是,当我在本地构建和安装gem、运行irb、需要gem时,我没有看到包含主动支持的方法?关于我做错了什么或如何调试有什么建议吗?谢谢! 最佳答案 您需要从ActiveSupport要求您需要的方法;默认情况下不添加它们。正如Yevgeniy在评论中提到的那样,如果您需要所有内容,则执行

随机推荐