动态加载帖子会导致java.lang.OutOfMemoryError

时间:2014-11-11 00:18:20

标签: java android multithreading android-asynctask

所以我在Google Play商店发布了我的第一个Android应用程序(COD Emeblem Tutorials)。我已经获得了很多下载,但是当你在动态加载的列表中滚动得足够远时,我注意到它崩溃了。

我加载教程的方法是调用对我网站的API调用。信息返回后,我会为每个教程显示一个ImageView&有一个异步任务去下载图像,如下所示。每当它到达第500个教程时,应用程序崩溃并出现以下错误。我认为它说堆已经没有内存了。知道如何防止这种情况发生吗?这是因为屏幕上有太多的ImageView?

public class DownloadImageTask extends AsyncTask<String, Integer, Bitmap> {
    ImageView bmImage;
    String id;
    ProgressBar progressbar;

    public DownloadImageTask(ImageView bmImage, ProgressBar progressbar, String id) {
        this.bmImage = bmImage;
        this.id = id;
        this.progressbar = progressbar;
    }

    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);
            //Log.v("COD","doInBackground");
        } catch (Exception e) {
            Log.e("Error", e.getMessage());
            e.printStackTrace();
        }
        return mIcon11;
    }


    protected void onPostExecute(Bitmap result) {
        progressbar.setVisibility(View.GONE);
        Image img = new Image(id, result);
        Brain.addImage(img);
        bmImage.setImageBitmap(result);
    }
}


> 11-10 19:11:59.952: E/dalvikvm-heap(1341): Out of memory on a 135440-byte allocation.
11-10 19:11:59.952: I/dalvikvm(1341): "AsyncTask #1" prio=5 tid=13 RUNNABLE
11-10 19:11:59.952: I/dalvikvm(1341):   | group="main" sCount=0 dsCount=0 obj=0x4262ab40 self=0x5cf7ee20
11-10 19:11:59.952: I/dalvikvm(1341):   | sysTid=1405 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=1623637296
11-10 19:11:59.952: I/dalvikvm(1341):   | state=R schedstat=( 0 0 0 ) utm=647 stm=148 core=0
11-10 19:11:59.952: I/dalvikvm(1341):   at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
11-10 19:11:59.952: I/dalvikvm(1341):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:623)
11-10 19:11:59.952: I/dalvikvm(1341):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:696)
11-10 19:11:59.952: I/dalvikvm(1341):   at com.codplayercards.codplayercards.DownloadImageTask.doInBackground(DownloadImageTask.java:30)
11-10 19:11:59.962: I/dalvikvm(1341):   at com.codplayercards.codplayercards.DownloadImageTask.doInBackground(DownloadImageTask.java:1)
11-10 19:11:59.962: I/dalvikvm(1341):   at android.os.AsyncTask$2.call(AsyncTask.java:287)
11-10 19:11:59.962: I/dalvikvm(1341):   at java.util.concurrent.FutureTask.run(FutureTask.java:234)
11-10 19:11:59.962: I/dalvikvm(1341):   at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
11-10 19:11:59.962: I/dalvikvm(1341):   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
11-10 19:11:59.962: I/dalvikvm(1341):   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
11-10 19:11:59.962: I/dalvikvm(1341):   at java.lang.Thread.run(Thread.java:841)
11-10 19:11:59.962: D/skia(1341): --- decoder->decode returned false
11-10 19:11:59.962: W/dalvikvm(1341): threadid=13: thread exiting with uncaught exception (group=0x41830898)
11-10 19:11:59.972: E/AndroidRuntime(1341): FATAL EXCEPTION: AsyncTask #1
11-10 19:11:59.972: E/AndroidRuntime(1341): java.lang.RuntimeException: An error occured while executing doInBackground()
11-10 19:11:59.972: E/AndroidRuntime(1341):     at android.os.AsyncTask$3.done(AsyncTask.java:299)
11-10 19:11:59.972: E/AndroidRuntime(1341):     at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
11-10 19:11:59.972: E/AndroidRuntime(1341):     at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
11-10 19:11:59.972: E/AndroidRuntime(1341):     at java.util.concurrent.FutureTask.run(FutureTask.java:239)
11-10 19:11:59.972: E/AndroidRuntime(1341):     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
11-10 19:11:59.972: E/AndroidRuntime(1341):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
11-10 19:11:59.972: E/AndroidRuntime(1341):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
11-10 19:11:59.972: E/AndroidRuntime(1341):     at java.lang.Thread.run(Thread.java:841)
11-10 19:11:59.972: E/AndroidRuntime(1341): Caused by: java.lang.OutOfMemoryError
11-10 19:11:59.972: E/AndroidRuntime(1341):     at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
11-10 19:11:59.972: E/AndroidRuntime(1341):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:623)
11-10 19:11:59.972: E/AndroidRuntime(1341):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:696)
11-10 19:11:59.972: E/AndroidRuntime(1341):     at com.codplayercards.codplayercards.DownloadImageTask.doInBackground(DownloadImageTask.java:30)
11-10 19:11:59.972: E/AndroidRuntime(1341):     at com.codplayercards.codplayercards.DownloadImageTask.doInBackground(DownloadImageTask.java:1)
11-10 19:11:59.972: E/AndroidRuntime(1341):     at android.os.AsyncTask$2.call(AsyncTask.java:287)
11-10 19:11:59.972: E/AndroidRuntime(1341):     at java.util.concurrent.FutureTask.run(FutureTask.java:234)
11-10 19:11:59.972: E/AndroidRuntime(1341):     ... 4 more
11-10 19:12:00.103: D/AbsListView(1341): unregisterIRListener() is called 
11-10 19:12:00.373: D/dalvikvm(1341): GC_FOR_ALLOC freed 168K, 13% free 85864K/98208K, paused 127ms, total 132ms
11-10 19:12:00.373: I/dalvikvm-heap(1341): Forcing collection of SoftReferences for 131776-byte allocation
11-10 19:12:00.513: D/dalvikvm(1341): GC_BEFORE_OOM freed <1K, 13% free 85863K/98208K, paused 134ms, total 142ms
11-10 19:12:00.513: E/dalvikvm-heap(1341): Out of memory on a 131776-byte allocation.
11-10 19:12:00.523: I/dalvikvm(1341): "AsyncTask #3" prio=5 tid=20 RUNNABLE
11-10 19:12:00.523: I/dalvikvm(1341):   | group="main" sCount=0 dsCount=0 obj=0x42f01eb8 self=0x61ad5728
11-10 19:12:00.523: I/dalvikvm(1341):   | sysTid=1532 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=1637026936
11-10 19:12:00.523: I/dalvikvm(1341):   | state=R schedstat=( 0 0 0 ) utm=1051 stm=119 core=0
11-10 19:12:00.523: I/dalvikvm(1341):   at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
11-10 19:12:00.523: I/dalvikvm(1341):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:623)
11-10 19:12:00.523: I/dalvikvm(1341):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:696)
11-10 19:12:00.523: I/dalvikvm(1341):   at com.codplayercards.codplayercards.DownloadImageTask.doInBackground(DownloadImageTask.java:30)
11-10 19:12:00.533: I/dalvikvm(1341):   at com.codplayercards.codplayercards.DownloadImageTask.doInBackground(DownloadImageTask.java:1)
11-10 19:12:00.533: I/dalvikvm(1341):   at android.os.AsyncTask$2.call(AsyncTask.java:287)
11-10 19:12:00.533: I/dalvikvm(1341):   at java.util.concurrent.FutureTask.run(FutureTask.java:234)
11-10 19:12:00.533: I/dalvikvm(1341):   at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
11-10 19:12:00.533: I/dalvikvm(1341):   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
11-10 19:12:00.533: I/dalvikvm(1341):   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
11-10 19:12:00.533: I/dalvikvm(1341):   at java.lang.Thread.run(Thread.java:841)
11-10 19:12:00.553: D/skia(1341): --- decoder->decode returned false
11-10 19:12:00.583: W/dalvikvm(1341): threadid=20: thread exiting with uncaught exception (group=0x41830898)
11-10 19:12:00.593: I/Process(1341): Sending signal. PID: 1341 SIG: 9

3 个答案:

答案 0 :(得分:1)

我强烈建议您使用Picasso

它是一个出色的库,可以满足您的所有需求,而且它具有出色的缓存,易于使用,您可以在代码中的任何位置使用它,从简单的imageview到列表(它可以循环使用)本身!)。 哦,而且,他们的文档非常出色!

答案 1 :(得分:0)

您是否将图片加载到列表视图? 如果要将图像加载到列表视图,请考虑仅加载所需的图像。 如果您的图像分辨率太大,请考虑将尺寸缩小到较小的分辨率。 最后,请确保回收位图以查找将移出可见范围的图像。

如果您已完成上述所有操作,则应该可以防止您在Android加载图片时出现内存不足错误。

如果你想轻松,自动处理图像加载,你应该考虑使用volley networkimageview,如Eugen Pechanec建议的那样。 Volley还具有图像缓存功能,可以在第二次尝试时加快图像加载速度。

答案 2 :(得分:0)

当您为处理多个图像集或大位图或某些动画内容的应用程序开发时,内存不足错误是非常常见的错误。在这种情况下,我们必须在处理图像或对象分配和释放时非常小心和高效。当分配超过堆限制或您的进程需要超过堆限制的内存量时,会出现OOM错误。

在Android中,每个应用程序都在Linux进程中运行。每个Linux进程都在其中运行虚拟机(Dalvik虚拟机)。进程可以要求的内存有一个限制,它对于不同的设备是不同的,并且对于手机和平板电脑也是不同的。当某个进程需要比其限制更高的内存时,会导致错误,即内存不足错误。

可能的原因:

我们遇到内存不足错误的原因有很多。其中一些是:

  1. 您正在进行一些持续需要大量内存的操作,并且在某些时候它超出了进程的最大堆内存限制。

  2. 您正在泄漏一些内存,即您没有使之前分配的对象符合垃圾收集(GC)的条件。这称为内存泄漏。

  3. 您正在处理大型位图并在运行时加载所有这些位图。你必须非常小心地处理大位图,只需加载你需要的大小而不是整个位图,然后进行缩放。

  4. 内存不足的最大原因是内存泄漏。

    在您的情况下,您正在使用位图并将其加载到内存中。 因此,最好修复这些位图的最大内存,这样当达到内存限制时,它将删除未使用的位图。 UniversalImageloader是一个很好的liabrary用于你的工作,他们提供了非常有效的缓存实现,你不需要自己加载位图,Liabrary将为你管理。 please refer the link