模拟器中的OutOfMemoryException

Pet*_*nas 11 java memory android

我真的不知道如何处理这种情况.突然之间,我在一个特定的Activity上得到一个OutOfMemoryException,并且每次在我正在开发的游戏中都遵循相同的路径时它是相同的.我在游戏中使用了很多Drawables.我在某处读到你应该经常执行Bitmap.recycle()来释放内存.但我几乎从不直接使用Bitmaps和我使用的Drawabels,我需要它们在屏幕上.

我使用Facebook和Parse SDK可能没有帮助.

现在我正在手机和模拟器上进行开发.在模拟器中,堆大小不能超过30 MB.我应该增加这个数字还是应该单独留下并尝试保持我的应用程序的内存消耗?

直到最近,我才假设,一旦我完成一个Activity并进入另一个,所有内容都将被垃圾收集,我开始新的示例代码:

private void startGamesActivity() {    
    Intent intent = new Intent(this, SS3GamesActivity.class);
    startActivity(intent);      
finish();   
}
Run Code Online (Sandbox Code Playgroud)

这不是真的吗?让我再详细说明一下.我有一个活动,有两个可能的Facebook播放器ListViews.OutOfMemoryException发生在我点击其中一个开始一个新的活动时,它应该比之前的活动更少的内存消耗!这就是为什么我不明白为什么甚至会发生OutOfMemoryException!在两个ListView收集垃圾后,应该有足够的内存!

所以我现在做的是分析我的堆消耗.我还下载了Eclipse Memory Analyzer.正在使用的最大内存块是1字节数组(byte [],boolean []),其数量为702,总大小为20,096 MB,其中最大值为6,240 MB,平均值为29,314 MB.这让我感到非常惊讶!它甚至没有在整个应用程序中增加很多.但是在仿真器中看到堆大小不会增加超过30MB,因为它有很大的潜力.

使用Eclipse Memory Analyzer它也给了我两个可能的内存泄漏罪魁祸首.

问题可疑1由""加载的"android.graphics.Bitmap"的一个实例占用6.543.416(28,00%)个字节.存储器在由""加载的"byte []"的一个实例中累积.

问题可疑2由""加载的类"android.content.res.Resources"占用5.212.968(22,31%)个字节.内存被累积在由""加载的"java.lang.Object []"的一个实例中.

结果并没有像我想象的那么直接.我认为从类名判断可能的嫌疑人是我的LruCache.我使用它来填充可能的播放器照片的Facebook缩略图,以便每次用户在ListView中滚动时不从网上加载它们.我不确定为什么它在我的应用程序开始时已经很大了.我已经尝试让它变小但没有运气.

这是我的MainActivity的创建:

// caching system
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);      
final int cacheSize = maxMemory / 16; // used to be 8, didnt help though

   mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
        @Override
        protected int sizeOf(String key, Bitmap bitmap) {
            // The cache size will be measured in kilobytes rather than
            // number of items.
            return bitmap.getByteCount() / 1024;
        }
    };  
Run Code Online (Sandbox Code Playgroud)

我还检查了第二个可能的嫌疑人,资源,并没有太多我能做的.似乎我正在使用我的所有布局对象,而且我现在无法使用更少的内容.

当我们在它的时候,像"onDestroy"这样的东西会有帮助吗?

public class ExampleActivity extends Activity {

    HashMap<String, String> meMap=new HashMap<String, String>();
    static ArrayList<String> meArray = new ArrayList<String>();

    protected void onDestroy() {        
        super.onDestroy();
        meMap.clear();
        meMap = null;

        meArray.clear();
        meArray = null;
    }

}
Run Code Online (Sandbox Code Playgroud)

因为我没有看到很多不同的内存消耗,这就是为什么我认为gc在aotomatically那样做.

我很乐意对我的问题采取一切可能的建议.我甚至可以提供更多信息,但此时我甚至不知道是什么.

StackTrace绿色:

05-06 07:37:12.373: I/dalvikvm(529): Wrote stack traces to '/data/anr/traces.txt'
05-06 07:37:12.523: E/dalvikvm-heap(529): Out of memory on a 3601936-byte allocation.
05-06 07:37:12.523: I/dalvikvm(529): "main" prio=5 tid=1 RUNNABLE
05-06 07:37:12.533: I/dalvikvm(529):   | group="main" sCount=0 dsCount=0 obj=0x409c1460 self=0x12810
05-06 07:37:12.533: I/dalvikvm(529):   | sysTid=529 nice=0 sched=0/0 cgrp=default handle=1074082952
05-06 07:37:12.533: I/dalvikvm(529):   | schedstat=( 8842421920 6327029011 3892 ) utm=778 stm=106 core=0
05-06 07:37:12.533: I/dalvikvm(529):   at android.graphics.Bitmap.nativeCreate(Native Method)
05-06 07:37:12.533: I/dalvikvm(529):   at android.graphics.Bitmap.createBitmap(Bitmap.java:605)
05-06 07:37:12.533: I/dalvikvm(529):   at android.graphics.Bitmap.createBitmap(Bitmap.java:551)
05-06 07:37:12.533: I/dalvikvm(529):   at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:437)
05-06 07:37:12.533: I/dalvikvm(529):   at android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:524)
05-06 07:37:12.533: I/dalvikvm(529):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:499)
05-06 07:37:12.533: I/dalvikvm(529):   at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:351)
05-06 07:37:12.533: I/dalvikvm(529):   at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:773)
05-06 07:37:12.533: I/dalvikvm(529):   at android.content.res.Resources.loadDrawable(Resources.java:1935)
05-06 07:37:12.533: I/dalvikvm(529):   at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
05-06 07:37:12.533: I/dalvikvm(529):   at android.widget.ImageView.<init>(ImageView.java:119)
05-06 07:37:12.533: I/dalvikvm(529):   at android.widget.ImageView.<init>(ImageView.java:109)
05-06 07:37:12.533: I/dalvikvm(529):   at java.lang.reflect.Constructor.constructNative(Native Method)
05-06 07:37:12.533: I/dalvikvm(529):   at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
05-06 07:37:12.533: I/dalvikvm(529):   at android.view.LayoutInflater.createView(LayoutInflater.java:586)
05-06 07:37:12.533: I/dalvikvm(529):   at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
05-06 07:37:12.533: I/dalvikvm(529):   at android.view.LayoutInflater.onCreateView(LayoutInflater.java:653)
05-06 07:37:12.543: I/dalvikvm(529):   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:678)
05-06 07:37:12.543: I/dalvikvm(529):   at android.view.LayoutInflater.rInflate(LayoutInflater.java:739)
05-06 07:37:12.543: I/dalvikvm(529):   at android.view.LayoutInflater.rInflate(LayoutInflater.java:742)
05-06 07:37:12.543: I/dalvikvm(529):   at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
05-06 07:37:12.543: I/dalvikvm(529):   at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
05-06 07:37:12.543: I/dalvikvm(529):   at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
05-06 07:37:12.543: I/dalvikvm(529):   at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:251)
05-06 07:37:12.543: I/dalvikvm(529):   at android.app.Activity.setContentView(Activity.java:1835)
05-06 07:37:12.543: I/dalvikvm(529):   at com.quizdom.SS7ChooseTopicsActivity.onCreate(SS7ChooseTopicsActivity.java:36)
05-06 07:37:12.543: I/dalvikvm(529):   at android.app.Activity.performCreate(Activity.java:4465)
05-06 07:37:12.543: I/dalvikvm(529):   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
05-06 07:37:12.543: I/dalvikvm(529):   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
05-06 07:37:12.543: I/dalvikvm(529):   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
05-06 07:37:12.543: I/dalvikvm(529):   at android.app.ActivityThread.access$600(ActivityThread.java:123)
05-06 07:37:12.543: I/dalvikvm(529):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
05-06 07:37:12.543: I/dalvikvm(529):   at android.os.Handler.dispatchMessage(Handler.java:99)
05-06 07:37:12.543: I/dalvikvm(529):   at android.os.Looper.loop(Looper.java:137)
05-06 07:37:12.543: I/dalvikvm(529):   at android.app.ActivityThread.main(ActivityThread.java:4424)
05-06 07:37:12.543: I/dalvikvm(529):   at java.lang.reflect.Method.invokeNative(Native Method)
05-06 07:37:12.543: I/dalvikvm(529):   at java.lang.reflect.Method.invoke(Method.java:511)
05-06 07:37:12.543: I/dalvikvm(529):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
05-06 07:37:12.543: I/dalvikvm(529):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
05-06 07:37:12.543: I/dalvikvm(529):   at dalvik.system.NativeStart.main(Native Method)
Run Code Online (Sandbox Code Playgroud)

SDJ*_*tie 4

显然我还没有看到您正在加载的位图,但我的猜测是它们比您显示它们的空间所需的大得多。例如,如果您下载一张 3000 x 2000 的图像,然后将其指定为仅为 300 x 200 的 ImageView 的源,则原始位图大小仍存储在内存中,只是显示得较小。重要的是,当从网络下载图像时,在将接收到的位图设置为 ImageView 的源之前,将其大小调整为显示大小。不这样做会消耗大量内存。

这是相当多的代码,因为在此过程中您需要防范许多不同的错误情况。我可以为您提供的最简单的解决方案是尝试毕加索库。您可以使用类似于下面所示的代码将要下载的 URL 传递给它,它将在后台线程上下载它,调整其大小,并在准备好时将其放入 ImageView 中。它还会缓存调整大小的版本,这样,如果您需要下载相同的图像,它会使用缓存的版本(如果它适合您要加载的 ImageView)。这意味着您也不会浪费网络流量。如果您需要在将图像放入 ImageView 之前对图像进行一些转换,您也可以通过提供一个Transform对象来实现。您还可以设置一个占位符图像,您应该将其放在drawable文件夹中,并且它将显示该图像,直到下载实际图像为止。

Picasso.with(context)
       .load("http://i.imgur.com/DvpvklR.png")
       .into(imageView);
Run Code Online (Sandbox Code Playgroud)