Android的毕加索的ImageView - 内存溢出异常MemoryLeak [英] Android Picasso ImageView - Out of Memory Exception MemoryLeak

查看:572
本文介绍了Android的毕加索的ImageView - 内存溢出异常MemoryLeak的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是新的Andr​​oid开发。我试图通过HTTP下载图像,并将它们存储ImageViews或可绘内。在这个例子中,我使用ImageViews。起初,我用了一个AsyncTask的下载这些图片(约500KB〜个),但是我决定用毕加索,因为我读过它更可靠。

在下面的code,我有20 ImageViews。每个图像的URL的是,大约400KB的图像。然而,加载所有这些之后,我发现我的 getUsedMem()比100MB更大。我不知道是什么原因造成这种内存泄漏。

你能帮助我吗?

 公共类示例扩展活动{
    众长getUsedMem()
    {
        长FREESIZE = 0L;
        长总计TOTALSIZE = 0L;
        长usedSize = -1L;
        尝试{
            运行时信息=调用Runtime.getRuntime();
            FREESIZE = info.freeMemory();
            总计TOTALSIZE = info.totalMemory();
            usedSize =总计TOTALSIZE - FREESIZE;
        }赶上(例外五){
            e.printStackTrace();
        }        返回usedSize;
    }    公共无效concatLogMessages(弦乐味精)
    {
        TextView的电视=(的TextView)findViewById(R.id.textView1);
        CharSequence的CS = tv.getText();        tv.setText(CS +\\ n+
                   图片#+味精+\\ n+
                   二手纪念品:+ getUsedMem()
                   );
    }    公共无效的LoadImage(最终目标的ImageView,字符串URL,最终诠释NUM){
        Picasso.with(本).load(URL).into(目标,新EmptyCallback(){
            @覆盖
            公共无效onerror的(){
                Example.this.concatLogMessages(毕加索的onError);
                super.onError();
            }            @燮pressLint(NewApi)@Override
            公共无效的onSuccess(){
                Example.this.concatLogMessages(毕加索的onSuccess+ NUM);
                super.onSuccess();
            }
        });
    }    @燮pressLint(NewApi)
    @覆盖
    公共无效的onCreate(捆绑savedInstanceState){
        super.onCreate(savedInstanceState);
        的setContentView(R.layout.main);        可绘制=新的ArrayList<&可绘制GT;();        //检查内存之前的一切
        concatLogMessages(0);        // ImageView的显示
        ImageView的此搜索=(ImageView的)findViewById(R.id.imageView1);
        ImageView的IMAGE2 =(ImageView的)findViewById(R.id.imageView2);
        ImageView的图像3 =(ImageView的)findViewById(R.id.imageView3);
        ImageView的图片4 =(ImageView的)findViewById(R.id.imageView4);
        ImageView的图像5 =(ImageView的)findViewById(R.id.imageView5);
        ImageView的图片6 =(ImageView的)findViewById(R.id.imageView6);
        ImageView的图片7 =(ImageView的)findViewById(R.id.imageView7);
        ImageView的图片8 =(ImageView的)findViewById(R.id.imageView8);
        ImageView的图片9 =(ImageView的)findViewById(R.id.imageView9);
        ImageView的image10 =(ImageView的)findViewById(R.id.imageView10);
        ImageView的image11 =(ImageView的)findViewById(R.id.imageView11);
        ImageView的image12 =(ImageView的)findViewById(R.id.imageView12);
        ImageView的image13 =(ImageView的)findViewById(R.id.imageView13);
        ImageView的image14 =(ImageView的)findViewById(R.id.imageView14);
        ImageView的image15 =(ImageView的)findViewById(R.id.imageView15);
        ImageView的image16 =(ImageView的)findViewById(R.id.imageView16);
        ImageView的image17 =(ImageView的)findViewById(R.id.imageView17);
        ImageView的image18 =(ImageView的)findViewById(R.id.imageView18);
        ImageView的image19 =(ImageView的)findViewById(R.id.imageView19);
        ImageView的image20 =(ImageView的)findViewById(R.id.imageView20);        / * *毕加索/
        ImageView的目标=(ImageView的)findViewById(R.id.picassoImageView);        的LoadImage(目标,image_url1,0);        //测试1-20图像视图...
        的LoadImage(image1的,R.String.image_url1,1);
        的LoadImage(IMAGE2,R.String.image_url2,2);
        的LoadImage(的Image3,R.String.image_url3,3);
        的LoadImage(图片4,R.String.image_url4,4);
        的LoadImage(图像5,R.String.image_url5,5);
        的LoadImage(图片6,R.String.image_url6,6);
        的LoadImage(图片7,R.String.image_url7,7);
        的LoadImage(图片8,R.String.image_url8,8);
        的LoadImage(图片9,R.String.image_url9,9);
        的LoadImage(image10,R.String.image_url10,10);
        的LoadImage(image11,R.String.image_url11,11);
        的LoadImage(image12,R.String.image_url12,12);
        的LoadImage(image13,R.String.image_url13,13);
        的LoadImage(image14,R.String.image_url14,14);
        的LoadImage(image15,R.String.image_url15,15);
        的LoadImage(image16,R.String.image_url16,16);
        的LoadImage(image17,R.String.image_url17,17);
        的LoadImage(image18,R.String.image_url18,18);
        的LoadImage(image19,R.String.image_url19,19);
        的LoadImage(image20,R.String.image_url20,20);
    }
}


解决方案

我不认为这是一个泄漏。

在Android的解开你的形象(即德codeS它的位图),它会使用每像素4个字节。计数的像素数,乘以4,然后20(数字图像的),你可能会得到接近100MB的身影。举例来说,如果你的图片有百万像素的分辨率,这将1,000,000×4×20 = 80MB。

您不应该一次加载所有这些图像。使用某种LRU高速缓存或类似的(或者用它处理缓存为你的通用图像装载机库),只有当你需要他们加载您的位图。

我强烈建议你阅读这篇文章,并在密切关注它的建议:
http://developer.android.com/training/displaying-bitmaps/load -bitmap.html

I am new to Android development. I'm trying to download images via HTTP and storing them inside of ImageViews or Drawables. In this example, I am using ImageViews. Initially, I used an AsyncTask to download these images (roughly ~500KB each), however I decided to use Picasso since I've read it is more reliable.

In the code below, I have 20 ImageViews. Each of the image url's is an image that is roughly 400KB. However, after loading all of them, I've noticed my getUsedMem() is greater than 100MB. I'm not sure what is causing this memory leak.

Could you please assist me?

public class Example extends Activity {
    public long getUsedMem()
    {
        long freeSize = 0L;
        long totalSize = 0L;
        long usedSize = -1L;
        try {
            Runtime info = Runtime.getRuntime();
            freeSize = info.freeMemory();
            totalSize = info.totalMemory();
            usedSize = totalSize - freeSize;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return usedSize;
    }

    public void concatLogMessages(String msg)
    {
        TextView tv = (TextView) findViewById(R.id.textView1);
        CharSequence cs = tv.getText();

        tv.setText(cs + "\n" + 
                   "Image #: " + msg + "\n" +
                   "Used Mem: " + getUsedMem()
                   );
    }

    public void loadImage(final ImageView target, String url, final int num)    {
        Picasso.with(this).load(url).into(target, new EmptyCallback(){
            @Override
            public void onError() {
                Example.this.concatLogMessages("Picasso onError");
                super.onError();
            }

            @SuppressLint("NewApi") @Override
            public void onSuccess() {
                Example.this.concatLogMessages("Picasso onSuccess " + num);
                super.onSuccess();
            }
        });
    }

    @SuppressLint("NewApi")
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        drawables = new ArrayList<Drawable>();

        // Check Memory Before Everything
        concatLogMessages("0");

        // Imageview to show
        ImageView image1 = (ImageView) findViewById(R.id.imageView1);
        ImageView image2 = (ImageView) findViewById(R.id.imageView2);
        ImageView image3 = (ImageView) findViewById(R.id.imageView3);
        ImageView image4 = (ImageView) findViewById(R.id.imageView4);
        ImageView image5 = (ImageView) findViewById(R.id.imageView5);
        ImageView image6 = (ImageView) findViewById(R.id.imageView6);
        ImageView image7 = (ImageView) findViewById(R.id.imageView7);
        ImageView image8 = (ImageView) findViewById(R.id.imageView8);
        ImageView image9 = (ImageView) findViewById(R.id.imageView9);
        ImageView image10 = (ImageView) findViewById(R.id.imageView10);
        ImageView image11 = (ImageView) findViewById(R.id.imageView11);
        ImageView image12 = (ImageView) findViewById(R.id.imageView12);
        ImageView image13 = (ImageView) findViewById(R.id.imageView13);
        ImageView image14 = (ImageView) findViewById(R.id.imageView14);
        ImageView image15 = (ImageView) findViewById(R.id.imageView15);
        ImageView image16 = (ImageView) findViewById(R.id.imageView16);
        ImageView image17 = (ImageView) findViewById(R.id.imageView17);
        ImageView image18 = (ImageView) findViewById(R.id.imageView18);
        ImageView image19 = (ImageView) findViewById(R.id.imageView19);
        ImageView image20 = (ImageView) findViewById(R.id.imageView20);

        /* Picasso */
        ImageView target = (ImageView) findViewById(R.id.picassoImageView);

        loadImage(target, image_url1, 0);

        // Test 1-20 image views...
        loadImage(image1, R.String.image_url1, 1);
        loadImage(image2, R.String.image_url2, 2);
        loadImage(image3, R.String.image_url3, 3);
        loadImage(image4, R.String.image_url4, 4);
        loadImage(image5, R.String.image_url5, 5);   
        loadImage(image6, R.String.image_url6, 6);
        loadImage(image7, R.String.image_url7, 7);
        loadImage(image8, R.String.image_url8, 8);
        loadImage(image9, R.String.image_url9, 9);
        loadImage(image10, R.String.image_url10, 10);
        loadImage(image11, R.String.image_url11, 11);
        loadImage(image12, R.String.image_url12, 12);
        loadImage(image13, R.String.image_url13, 13);
        loadImage(image14, R.String.image_url14, 14);
        loadImage(image15, R.String.image_url15, 15);
        loadImage(image16, R.String.image_url16, 16);
        loadImage(image17, R.String.image_url17, 17);
        loadImage(image18, R.String.image_url18, 18);
        loadImage(image19, R.String.image_url19, 19);
        loadImage(image20, R.String.image_url20, 20);
    }
}

解决方案

I don't think it's a leak.

When Android "unwraps" your image (i.e. decodes it to bitmap), it will use 4 bytes per pixel. Count the number of pixels, multiply that by 4 and then by 20 (number of your images) and you'll probably get close to the 100mb figure. For instance, if your images have 1,000,000 pixel resolution, it would be 1,000,000 x 4 x 20 = 80mb.

You should not load all these images at once. Use some kind of LRU cache or similar (or alternatively use Universal Image Loader library which handles caching for you) and only load your bitmaps when you need them.

I highly recommend reading this article and following its advices very closely: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

这篇关于Android的毕加索的ImageView - 内存溢出异常MemoryLeak的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆