Search code examples
javaandroidmemorybitmapuniversal-image-loader

Out-of-memory errors using ImageGetter to grab images from HTML


I am writing an application to display posts from a website and using Html.fromHtml to do this. However if I open an article it immediately uses about 25MB of memory to load the images. This would be acceptable only reloading the same article causes another 25MB jump even though the images are stored on the device. I have looked around and tried a huge amount of proposed solution. I feel I need to recycle the Bitmaps only I'm not sure where to do this. Here's the code:

public class ImageGetter implements Html.ImageGetter {
private Context c;
private TextView container;
private ImageLoader imageLoader;
private DisplayImageOptions options;
private UrlImageDownloader urlDrawable;

public ImageGetter(View t, Context c) {
    this.c = c;
    this.container = (TextView)t;

    imageLoader = ImageLoader.getInstance();
    options = new DisplayImageOptions.Builder().cacheOnDisk(true).cacheInMemory(false).imageScaleType(ImageScaleType.EXACTLY)
            .showImageOnLoading(R.color.darkcolorPrimary).bitmapConfig(Bitmap.Config.RGB_565).resetViewBeforeLoading(true).build();
}

@Override
public Drawable getDrawable(String source) {
    urlDrawable = new UrlImageDownloader(c.getResources(), source);
    imageLoader.loadImage(source, options, new SimpleListener(urlDrawable));
    return urlDrawable;
}

private class SimpleListener extends SimpleImageLoadingListener
{
    UrlImageDownloader urlImageDownloader;

    public SimpleListener(UrlImageDownloader downloader) {
        super();
        urlImageDownloader = downloader;
    }

    @Override
    public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
        int width = loadedImage.getWidth();
        int height = loadedImage.getHeight();

        int newWidth = width;
        int newHeight = height;

        if( width > container.getWidth() ) {
            newWidth = container.getWidth();
            newHeight = (newWidth * height) / width;
        }

        Drawable result = new BitmapDrawable(c.getResources(), loadedImage);
        result.setBounds(0, 0, newWidth, newHeight);

        urlImageDownloader.setBounds(0, 0, newWidth, newHeight);
        urlImageDownloader.drawable = result;

        container.setText(container.getText());
    }
}

public class UrlImageDownloader extends BitmapDrawable
{
    public Drawable drawable;

    /**
     * Create a drawable by decoding a bitmap from the given input stream.
     *
     * @param res
     * @param is
     */
    public UrlImageDownloader(Resources res, InputStream is) {
        super(res, is);
    }

    /**
     * Create a drawable by opening a given file path and decoding the bitmap.
     *
     * @param res
     * @param filepath
     */
    public UrlImageDownloader(Resources res, String filepath) {
        super(res, filepath);
        drawable = new BitmapDrawable(res, filepath);
    }

    /**
     * Create drawable from a bitmap, setting initial target density based on
     * the display metrics of the resources.
     *
     * @param res
     * @param bitmap
     */
    public UrlImageDownloader(Resources res, Bitmap bitmap) {
        super(res, bitmap);
    }

    @Override
    public void draw(Canvas canvas) {
        // override the draw to facilitate refresh function later
        if(drawable != null) {
            drawable.draw(canvas);
        }
    }
}

}


Solution

  • Solved. There was a memory leak involving the TextView that was storing the images. If you're having a problem like this I recommend using Eclipse MAT to identify the memory leak.