Android位图imageview内存泄漏

2023-11-24

我将 4x4 imageView 放入活动(BoardActivity)中,用户可以通过单击它们来更改图像。使用 HTC Desire (Android 2.2.2),我在大约 30 分钟的密集使用中遇到 OOM(内存不足)-编辑:此活动第 16 次开始-,但没有其他设备产生这个(android 2.1和android 2.2.1)。我是否可能在使用位图/图像视图时犯了一些错误并导致了此错误? 首先,我将所有资源 ID 加载到地图中:

private Map<String, Integer> imageResourceMap;
imageResourceMap = new HashMap<String, Integer>();
        imageResourceMap.put("a", R.drawable.a);
        imageResourceMap.put("b", R.drawable.b);
        imageResourceMap.put("c", R.drawable.c);
//... I store 55 drawable's resourceId in this map

然后我调整每个图像的大小并将其保存为位图,在地图中表示:

private static Map<String, Bitmap> imageBitmap;

    private void loadBitmaps(int imagesSize) {

    for (String s : imageResourceMap.keySet()) {
        Bitmap tmp = getBitmapFromRes(imageResourceMap.get(s), imagesSize);
        imageBitmap.put(s, tmp);
    }
}

private Bitmap getBitmapFromRes(int resId, int imageSize) {
    Bitmap b = null;
    try {
        // Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;

        InputStream fis = getResources().openRawResource(resId);
        BitmapFactory.decodeStream(fis, null, o);
        fis.close();

        int scale = 1;
        if (o.outHeight > imageSize || o.outWidth > imageSize) {
            scale = (int) Math.pow(2, (int) Math.round(Math.log(imageSize / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
        }

        // Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        fis = getResources().openRawResource(resId);
        b = BitmapFactory.decodeStream(fis, null, o2);
        fis.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return b;
}

我将 imageView 保存在一个数组中,并使用此函数初始化所有图像:

private static ImageView[][] imageViews;

private ImageView getImage(String name) {
        MyImageView item = new MyImageView(this, i, j, c + "");
        item.setImageBitmap(imageBitmap.get(name));
        item.setAdjustViewBounds(true);
        return item;
    }

当我需要更改图像时,我只需更改其资源:

imageViews[i][j].setImageBitmap(imageBitmap.get("a"));

在完成活动之前,我回收了位图:

private void recycleImageBitmaps() {
    for (Bitmap b : imageBitmap.values()) {
        if (b != null) {
            b.recycle();
        }
    }

}

在 AndroidManifest.xml 中,我声明此活动为“singleTask”:

<activity android:name=".game.board.BoardActivity" android:launchMode="singleTask">
    </activity>

在此应用程序(游戏)中,我们多次重新打开此活动...... 我做错了什么?这会导致内存不足错误吗?

更正更正了 getBitmapFromRes,如下所示:

private Bitmap getBitmapFromRes(int resId, int imageSize) {
    Bitmap tmp = null;
    Bitmap b = null;
    try {
        // Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;

        InputStream fis = getResources().openRawResource(resId);
        tmp = BitmapFactory.decodeStream(fis, null, o);
        fis.close();

        int scale = 1;
        if (o.outHeight > imageSize || o.outWidth > imageSize) {
            scale = (int) Math.pow(2, (int) Math.round(Math.log(imageSize / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
        }

        // Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        fis = getResources().openRawResource(resId);
        b = BitmapFactory.decodeStream(fis, null, o2);
        fis.close();
    } catch (IOException e) {
        e.printStackTrace();
    }finally{
        if(tmp != null){
            tmp.recycle();
            tmp = null;
        }
    }
    return b;
}

HTC在该活动第11次开始时仍然死机。

EDIT:该活动(BoardActivity)从一个活动(MenuActivity)启动,该活动有4个imageButton,并且位于Tabhost活动中。 imageButtons 声明如下所示:

<ImageButton
    android:id="@+id/game_menu_CreateButton"
    android:layout_width="120dip" 
    android:layout_height="120dip"
    android:layout_alignRight="@+id/textView1"
    android:layout_alignTop="@+id/textView1"
    android:background="@drawable/create" 
    android:layout_marginRight="1sp"
    android:layout_marginTop="10sp"
     />

当我从 MenuActivity 启动 BoardActivity 时,我不调用finish()在 MenuActivity 中,当我打电话时finish()在 BoardActivity 中,我没有启动新的意图,因此它只是返回到已经打开的 MenuActivity。到了第 16 轮,我就 OOM 了。


要减少内存,您可以尝试以下操作:

  • 将可绘制对象转换为位图后,您可以将 imageResourceMap 设置为 null。这将卸载 3 个可绘制对象。
  • 避免存储对 imageView 的引用。即使 imageView 从 UI 中删除,您也可能会存储它们
  • 更频繁地回收位图。不仅仅是 onDestroy,只要您知道某个位图没有被使用,您就可以回收它。

编辑:基于评论中的对话:BitmapFactory.decodeStream(fis, null, o) 返回的位图未分配给任何变量,因此不会被回收。 Android 2.2 和 2.3 在这方面会有漏洞。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android位图imageview内存泄漏 的相关文章

随机推荐

  • 无法解析符号 AndroidJUnit4

    我正在尝试为我的应用程序添加登录facebook 但是当我添加执行此操作所需的存储库时 它导致了一个错误 AndroidJUnit4 现在无法解析 示例InstrumentedTest java package com example us
  • Cordova 想要 android-19,我有 android-20

    这里有很多关于运行 cordova add platform android 命令的问题的问题 我已经尝试了每种有目的的解决方案 但没有一个对我有帮助 错误信息 sandbox hello cordova platform add andr
  • CMake 中 CUDA 库的链接

    我正在使用 CMake 3 10 并且在将已编译的库链接到 CMake 中的测试可执行文件时遇到问题 我进行了大量搜索 发现在早期版本中存在一个问题 即无法在结果可执行文件中链接中间库 我无法判断这是否已解决或仍然是一个问题 我的 CMak
  • 重写取消应用方法

    我有一个case来自图书馆课程 我想覆盖unapply method 减少参数数量我需要通过对其进行模式匹配 我这样做 object ws1 a library class case class MyClass a Int b String
  • 我需要 T-SQL 将数据导出到 CSV(带标题)的最佳实践

    我需要做的是使用 T SQL 将数据导出到 CSV 文件 我很困惑有很多方法可以做到这一点 我不知道选择哪一种 请帮我确认以下内容 据我所知大概有3种方法 请您帮我确认一下 使用 Microsoft Jet OLEDB 4 0 如下所示 I
  • GlassFish v3 和 glassfish-maven-plugin (Mac)

    我正在尝试使用 glassfish maven plugin https maven glassfish plugin dev java net 与 GlassFish v3 我在 Mac 上并使用 Eclipse 但我似乎无法部署我的 W
  • Interface Builder(iPhone dev)自定义按钮背景图像不考虑拉伸设置

    我正在尝试使用 Interface Builder 中的背景图像创建自定义按钮 图像具有可拉伸和不可拉伸的部分 以便可以调整其大小 IB 公开了 Stretching 属性以实现此目的 但我输入的任何值都不会影响按钮的显示方式 它始终完全拉
  • Flexbox - 填充剩余空间[重复]

    这个问题在这里已经有答案了 我有一个像这样的基本弹性盒布局 body html height 100 width 100 container width 100 background grey display flex flex direc
  • 使用 CSS 和 Bootstrap 创建自定义复选框

    我使用引导框架进行了以下标记 div class col md 4 div class custom container img class center block img responsive img circle invite con
  • 50% 内联块未彼此相邻显示

    说我有 span class ib half span span class ib half span and ib half display inline block width 50 我希望这两个跨度并排显示 但它们不会 没有边距 内边
  • 当作用域被销毁时,我是否需要“取消监视”作用域变量?

    以下是来自 Angular 的文档 我正在观察属于此范围的几个变量 以构建过滤字符串ng grid 当这个作用域被销毁时 我是否需要通过调用返回值来取消监视它们 scope watch 或者范围的破坏足以解决这个问题吗 如果正在监视的变量不
  • webkit/chrome Web Inspector 资源检查如何工作?

    我总是想知道如何资源检查从事 webkit safari chrome Web Inspector 工作 浏览器必须提供本机 BPI 或 JavaScript 的某些内容来显示查询列表及其时间线 二进制 API 称为什么 我可以使用相同的
  • 编写 cypress 测试时如何选择同名的 div 元素

    我正在使用 cypress 为我们的新应用程序创建 E2E 测试 该应用程序有一个菜单 其中包含用于在地图屏幕上显示不同数据的按钮 所有这些按钮都有相同的 div 名称 我可以通过输入按钮的文本名称来区分 cy get div sb ite
  • 如何在django中自动更改模型字段

    我有一个模型 我想知道是否可以设置触发模型字段更改的条件 例如 我有一个模型 class BillboardTracker models Model client name models CharField max length 400 e
  • 从java在mysql中创建数据库

    你能帮忙解决这个问题吗 我正在尝试创建并使用一个名为 TIGER 的数据库 如果我在 MySQL 中创建数据库并且它运行完美 那么我没有问题 我想做的是从 Java 创建它 这样 当代码第一次运行时 它会创建数据库作为初始启动的一部分 如果
  • 5000:类“..”必须是“flash.display.MovieClip”的子类,因为它链接到该类型的库元件

    这是带有完整路径的标题错误 psf Home Dropbox Development Repositories GIT i cc Powerhouse Notes master flash lib libnote NotesCore as
  • 来自 AXUIElement 的 CGWindowID

    我正在尝试使用辅助功能 API 自动化外部 OSX 应用程序 一些 应用程序的状态无法通过 API 获得 因此我通过以下方式获取它 屏幕刮擦 为此 我需要获取可访问性对象的 CGWindowID 窗口角色 有没有直接的方法来获取 窗口角色
  • Json.NET 可以反序列化带有点表示法的扁平化 JSON 字符串吗?

    我有一个扁平化的 JSON CaseName John Doe v State CaseDate
  • 文本下划线并留有空格。可以通过 html 和 css 实现吗?

    我花了几个小时在这上面 我试图描述所附图片上的问题 需要用白线包裹文本 行与文本之间留有一些空格 我想到的第一个解决方案 只是使用 smth 行 margin top 20px 将文本放在线上并为文本容器提供自定义背景 例如灰色 但这不是解
  • Android位图imageview内存泄漏

    我将 4x4 imageView 放入活动 BoardActivity 中 用户可以通过单击它们来更改图像 使用 HTC Desire Android 2 2 2 我在大约 30 分钟的密集使用中遇到 OOM 内存不足 编辑 此活动第 16