内存泄漏与位图和自定义图像视图(Android)

时间:2014-08-05 15:26:55

标签: java android memory-leaks bitmap

在我的Android应用中,我使用自定义ImageView类(横幅)来显示从Facebook事件中提取的图像。在运行应用程序时,我注意到在运行应用程序时有一个很大的堆大小(120 MB)。我使用MAT,我认为我已将其缩小到byte[],然后最终缩小到ImageView。请查看下面的图片,看看我是如何得出这个结论的。

enter image description here enter image description here enter image description here

现在,我已经阅读了similar posts,我尝试使用WeakReferences回收我的位图,创建一个缓存,但似乎没有任何东西减少内存大小。 然而,回收我的位图给我一个错误,说我不能使用循环位图(我觉得这可能是一个暗示,因为它将我的位图保留在内存中?)。

应用程序在我的手机上运行缓慢(即使内存平均为100 MB,它甚至只表示CPU使用率为1.5%)。我将发布我的Banner子类以及如何下载图像以查看是否有人可以帮助我。

Banner.java

public class Banner extends ImageView {
    public Banner(Context context) {
        super(context);
    }

    public Banner(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public Banner(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = 400;
        if (getDrawable() != null && getDrawable().getIntrinsicWidth() != 0){
            height = width * getDrawable().getIntrinsicHeight() / getDrawable().getIntrinsicWidth();
            if (height < 500)
                height = 700;
        }
        setMeasuredDimension(width, height);
        setColorFilter(Color.rgb(123, 123, 123), android.graphics.PorterDuff.Mode.MULTIPLY);
    }
    public void onDestroy(){
        Drawable drawable = this.getDrawable();
        if (drawable instanceof BitmapDrawable) {
            BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
            Bitmap bitmap = bitmapDrawable.getBitmap();
            bitmap.recycle();
        }
        this.setImageBitmap(null);
    }
}

BannerLoader.java

public class BannerLoader{
    private String url;
    private WeakReference<ImageView> cover;
    private LruCache<String, WeakReference<Bitmap>> mMemoryCache;
    final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
    final int cacheSize = maxMemory / 8;
    public BannerLoader(String cover_url, WeakReference<ImageView> cover, Drawable defaultDrawable) {
        this.url = cover_url;
        this.cover = cover;
        cover.get().setBackground(defaultDrawable);
        mMemoryCache = new LruCache<String, WeakReference<Bitmap>>(cacheSize) {
            @Override
            protected int sizeOf(String key, WeakReference<Bitmap> bitmap) {
                // The cache size will be measured in kilobytes rather than
                // number of items.
                return bitmap.get().getByteCount() / 1024;
            }
        };
        new DownloadImage().execute();
    }
    public void addBitmapToMemoryCache(String key, WeakReference<Bitmap> bitmap) {
        if (getBitmapFromMemCache(key) == null) {
            mMemoryCache.put(key, bitmap);
        }
    }
    public WeakReference<Bitmap> getBitmapFromMemCache(String key) {
        return mMemoryCache.get(key);
    }
    class DownloadImage extends AsyncTask<Void, Void, WeakReference<Bitmap>>{
        protected WeakReference<Bitmap> doInBackground(Void... params){
            try {
                final WeakReference<Bitmap> cachedBitmap = getBitmapFromMemCache(url);
                if (cachedBitmap != null){
                    return cachedBitmap;
                } else{
                    URL pictureURL = new URL(url);
                    HttpGet httpRequest = null;

                    httpRequest = new HttpGet(pictureURL.toURI());

                    HttpClient httpclient = new DefaultHttpClient();
                    HttpResponse response = (HttpResponse) httpclient
                            .execute(httpRequest);

                    HttpEntity entity = response.getEntity();
                    BufferedHttpEntity b_entity = new BufferedHttpEntity(entity);
                    InputStream input = b_entity.getContent();

                    WeakReference<Bitmap> bitmap = new WeakReference<Bitmap>(BitmapFactory.decodeStream(input));
                    addBitmapToMemoryCache(url, bitmap);
                    return bitmap;
                }
            } catch(Exception ex){
                ex.printStackTrace();
            }
            return null;
        }
        public void onPostExecute(WeakReference<Bitmap> image){
            if (image != null && cover.get() != null){
                cover.get().setImageBitmap(image.get());
            }
        }
    }
}

因此,作为一个例子,我下载了这样的图像:

new BannerLoader(tempEvent.getCover_url(), new WeakReference<ImageView>(thumb_image), context.getResources().getDrawable(R.drawable.placeholder));

感谢您的帮助!

0 个答案:

没有答案