如何清除内存以防止java.lang.OutOfMemoryError

时间:2014-07-24 13:48:18

标签: java android out-of-memory

我有一个包含大量页面的应用程序,每个页面都有自己的图像,这些图像是使用asynctask从web加载的。问题是当你打开和关闭很多页面时,一段时间后它就会出现内存错误。离开活动时如何从内存中清除图像以防止这种情况?

图像由此Asynctask加载:

private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
        ImageView bmImage;

        public DownloadImageTask(ImageView bmImage) {
            this.bmImage = bmImage;
        }

        protected Bitmap doInBackground(String... urls) {
            String urldisplay = urls[0];
            Bitmap mIcon11 = null;
            try {
                InputStream in = new java.net.URL(urldisplay).openStream();
                mIcon11 = BitmapFactory.decodeStream(in);
            } catch (Exception e) {
                Log.e("Error", e.getMessage());
                e.printStackTrace();
            }
            return mIcon11;
        }

        protected void onPostExecute(Bitmap result) {
            bmImage.setImageBitmap(result);
        }
    }

致电:

new DownloadImageTask((ImageView) findViewById(R.id.ivCard)).execute("http://myurl.com/example.png");

使用不同的值和不同的图像打开和关闭此活动。打开此活动的某些实例后,它会出现以下内存错误:

07-24 16:37:57.870  27717-28014/com.yigitserin.hsboard E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
    java.lang.RuntimeException: An error occured while executing doInBackground()
            at android.os.AsyncTask$3.done(AsyncTask.java:299)
            at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
            at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
            at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
            at java.util.concurrent.FutureTask.run(FutureTask.java:137)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
            at java.lang.Thread.run(Thread.java:856)
     Caused by: java.lang.OutOfMemoryError
            at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
            at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:650)
            at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:722)
            at com.yigitserin.hsboard.HeroActivity$DownloadImageTask.doInBackground(HeroActivity.java:137)
            at com.yigitserin.hsboard.HeroActivity$DownloadImageTask.doInBackground(HeroActivity.java:125)
            at android.os.AsyncTask$2.call(AsyncTask.java:287)
            at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
            at java.util.concurrent.FutureTask.run(FutureTask.java:137)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
            at java.lang.Thread.run(Thread.java:856)

如何在用户退出此活动的一个实例后从内存中删除图像?

4 个答案:

答案 0 :(得分:2)

您需要调用位图的循环方法,例如。在你的活动onDestroy / onStop方法。见Recycle ImageView's Bitmap

答案 1 :(得分:1)

在我看来,你必须使用第三方库,如: -

Universal Loader

Picasso

URL helper

上面的lib自动维护位图内存。

答案 2 :(得分:0)

我认为你应该在finally块中关闭流然后尝试。我希望这可以排除一种可能性,然后我们可以考虑其他优化技术。

答案 3 :(得分:0)

您可能不需要“清除”内存,而是对要加载的Bitmap进行下采样以避免内存不足异常。关于如何处理和加载大型位图文件,有一些good tutorials。例如:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
    int reqWidth, int reqHeight) {

// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);

// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}

这里不是加载整个位图,而是可以在加载到内存之前缩小图像并完全避免这个问题。

如果你仍然遇到问题,我会更早关注为什么你的应用程序会保留对不再使用的大量图像的引用。当页面被销毁时,如果你的应用程序设置正确,那么位图应该像其他任何东西一样被垃圾收集。