草庐IT

android - 位图内存泄漏 - Android

coder 2023-12-24 原文

我的应用程序内存泄漏,多次触发 GC 并导致性能问题。我使用 MAT 生成了一份泄漏可疑报告。这是报告:

问题嫌疑人1: “”加载的一个“android.graphics.Bitmap”实例占用 4,194,368 (20.13%) 字节。内存累积在“.”加载的“byte[]”的一个实例中。

问题嫌疑人2: “android.content.res.Resources”类由“”加载,占用 3,962,504 (19.02%) 字节。内存累积在“”加载的“java.lang.Object[]”的一个实例中。

疑点3: “”加载的一个“android.graphics.Bitmap”实例占用 3,145,792 (15.10%) 字节。内存累积在“.”加载的“byte[]”的一个实例中。

从报告来看很明显内存泄漏是因为位图。我已经研究了很多但无法纠正这种泄漏。请帮帮我。我正在使用 ImageLoader 类来下载和显示位图。要使用此类,我只需调用 displayImage() 方法即可。这是代码:

public class ImageLoader {

    private static ImageLoader imageLoader;
    private int maxNoOfConnections = 4;
    FileCache fileCache;
    ExecutorService executorService;
    HttpURLConnection conn;
    InputStream is;
    OutputStream os;
    PhotosLoader photosLoader;
    Handler handler;
    Bitmap bitmap;

    private ImageLoader(Context context) {
        fileCache = new FileCache(context);
        executorService = Executors.newFixedThreadPool(maxNoOfConnections);
        handler = new Handler();
    }

    public static ImageLoader getInstance(Context context) {
        if (imageLoader == null)
            imageLoader = new ImageLoader(context);
        return imageLoader;
    }

    public void displayImage(String url, ProgressBar pBar, ImageView imageView) {
        photosLoader = new PhotosLoader(url, imageView, pBar);
        executorService.submit(photosLoader);
    }

    private Bitmap getBitmap(String url) {
        File f = fileCache.getFile(url);

        bitmap = decodeFile(f);
        if (bitmap != null)
            return bitmap;

        try
        {
            URL imageUrl = new URL(url);
            conn = (HttpURLConnection) imageUrl.openConnection();
            conn.setConnectTimeout(30000);
            conn.setReadTimeout(30000);
            conn.setInstanceFollowRedirects(true);
            is = conn.getInputStream();
            os = new FileOutputStream(f);
            Utils.CopyStream(is, os);
            os.close();
            bitmap = decodeFile(f);
            return bitmap;
        } catch (Exception ex)
        {
            Log.e("inNews", "Image Url Malformed");
            return null;
        }
    }

    private Bitmap decodeFile(File f) {
        try
        {
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(new FileInputStream(f), null, o);

            final int REQUIRED_SIZE = 70;
            int width_tmp = o.outWidth, height_tmp = o.outHeight;
            int scale = 1;
            while (true)
            {
                if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE)
                    break;
                width_tmp /= 2;
                height_tmp /= 2;
                scale *= 2;
            }

            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize = scale;
            return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
        } catch (FileNotFoundException e)
        {
        }
        return null;
    }

    class PhotosLoader implements Runnable {
        String url;
        ImageView imageView;
        ProgressBar pBar;
        Bitmap bmp;

        public PhotosLoader(String url, ImageView imageView, ProgressBar pBar) {
            this.url = url;
            this.imageView = imageView;
            this.pBar = pBar;
        }

        @Override
        public void run() {
            bmp = getBitmap(url);
            handler.post(new Runnable() {
                @Override
                public void run() {
                    if (bmp != null)
                    {
                        pBar.setVisibility(View.GONE);
                        imageView.setImageBitmap(bmp);
                    } else
                    {
                        pBar.setVisibility(View.GONE);
                        imageView.setImageResource(R.drawable.img_no_image_grid);
                    }
                }
            });
        }
    }

}

请帮我改正我的代码。谢谢!

注意:我没有使用 bitmap.recycle() 因为文档说 Honeycomb 后 GC 收集位图并且不再需要强制回收它 !

最佳答案

内存泄漏问题一直是Java的问题。 我理解你的代码,代码简单的imagecache工具。检查 SampleSize 值和执行程序服务仅在一个线程上运行。四个线程有大内存和这个后台线程操作。您的“处理程序”交换为“runOnUIThread”

你应该使用;

Activity Activity = (Activity)imageView.getContext();

__activity__.runOnUIThread(new Runnable()
{
 if (bmp != null)
                    {
                        pBar.setVisibility(View.GONE);
                        imageView.setImageBitmap(bmp);
                    } else
                    {
                        pBar.setVisibility(View.GONE);
                        imageView.setImageResource(R.drawable.img_no_image_grid);
                    }
});

关于android - 位图内存泄漏 - Android,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14937158/

有关android - 位图内存泄漏 - Android的更多相关文章

  1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  2. ruby-on-rails - Ruby 中的内存模型 - 2

    ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序

  3. 安卓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,打开命令窗口,并将路

  4. 键删除后 ruby​​ 哈希内存泄漏 - 2

    你好,我无法成功如何在散列中删除key后释放内存。当我从哈希中删除键时,内存不会释放,也不会在手动调用GC.start后释放。当从Hash中删除键并且这些对象在某处泄漏时,这是预期的行为还是GC不释放内存?如何在Ruby中删除Hash中的键并在内存中取消分配它?例子:irb(main):001:0>`ps-orss=-p#{Process.pid}`.to_i=>4748irb(main):002:0>a={}=>{}irb(main):003:0>1000000.times{|i|a[i]="test#{i}"}=>1000000irb(main):004:0>`ps-orss=-p

  5. ruby-on-rails - HTTParty 的内存问题和下载大文件 - 2

    这会导致Ruby出现内存问题吗?我知道如果大小超过10KB,Open-URI会写入TempFile。但是HTTParty会在写入TempFile之前尝试将整个PDF保存到内存吗?src=Tempfile.new("file.pdf")src.binmodesrc.writeHTTParty.get("large_file.pdf").parsed_response 最佳答案 您可以使用Net::HTTP。参见thedocumentation(特别是标题为“流媒体响应机构”的部分)。这是文档中的示例:uri=URI('http://e

  6. ruby-on-rails - 内存中具有相同 ID 的更多对象? - 2

    在部署在heroku上的Rails应用程序(v:3.1)中,我在内存中获得了更多具有相同ID的对象。我的heroku控制台日志:>>Project.find_all_by_id(92).size=>2>>ActiveRecord::Base.connection.execute('select*fromprojectswhereid=92').to_a.size=>1这怎么可能?可能是什么问题? 最佳答案 解决方案根据您的SQL查询,您的数据库中显然没有重复条目。也许您的类项目中的size或length方法已被覆盖。我试过find_

  7. ruby - rails 3.0.7 内存泄漏 - 2

    我的两个不同的Rails应用程序的内存有一些奇怪的问题。这两个应用程序都使用rails3.0.7。每个Controller请求分配20-30-50MB的内存。在生产模式下,这个数量减少到5-10。但这是同样的事情。这是两个应用程序使用的gem列表:gem'pg'gem'haml'gem'sass'gem'devise'gem'simple_form'gem'state_machine'gem"globalize3","0.1.0.beta"gem"easy_globalize3_accessors"gem'paperclip'gem'andand'关闭所有这些gem不会给我任何结果。我

  8. ruby - 如何强制 Ruby 释放内存给操作系统 - 2

    正如标题,我有一个处理大量数据的ruby​​程序。该程序占用了所有内存,其中调用了系统命令hostname,并且发生错误无法分配内存-主机名我试过GC.start但它不起作用。那么如何强制ruby释放未使用的内存呢?OK,这是别人的测试代码,最后报错是big_var被回收了。但是内存仍然没有释放。require"weakref"defreportputs"#{param}:\t\tMemory"+`psax-opid,rss|grep-E"^[[:space:]]*#{$$}"`.strip.split.map(&:to_i)[1].to_s+'KB'endbig_var=""#big

  9. ruby - 如何在 Ruby 中从内存中 HTTP 发布流数据? - 2

    我想上传我在运行时用Ruby生成的数据,就像从block中提供上传数据一样。我找到的所有示例仅展示了如何流式传输必须在请求之前位于磁盘上的文件,但我不想缓冲该文件。除了滚动我自己的套接字连接之外,最好的解决方案是什么?这是一个伪代码示例:post_stream('127.0.0.1','/stream/')do|body|generate_xmldo|segment|body 最佳答案 有效的代码。require'thread'require'net/http'require'base64'require'openssl'class

  10. ruby-on-rails - 如何仅修改内存中的 zip 文件? - 2

    我有一个Ruby应用程序,我需要修改现有的zip文件。我想在内存中构建zip文件并流回字节,而无需将文件写入文件系统。如果我最终在Heroku上托管它,我认为我无法写入文件系统。有谁知道这样做的方法吗?我看了Zip::ZipFile但看起来它总是想写入文件系统。我想“基于java实现”我将能够只获取压缩文件的字节,这可以在java中完成,但我看不到这样做的方法。编辑:我要问的与此基本相同,但针对Ruby而不是Python:Functiontocreatein-memoryzipfileandreturnashttpresponse 最佳答案

随机推荐