我不知道何时或为何发生的 OutOfMemoryError

OutOfMemoryError that I don't know when or why happened

所以我刚刚注意到 Crashlytics 上的崩溃。显然它对 3 个不同的用户发生了 4 次。其中一个拥有相当不错的设备 (Nexus 5)。

堆栈跟踪:

Fatal Exception: java.lang.OutOfMemoryError: Failed to allocate a 4194316 byte allocation with 3271760 free bytes and 3MB until OOM
   at dalvik.system.VMRuntime.newNonMovableArray(VMRuntime.java)
   at android.graphics.Bitmap.nativeCreate(Bitmap.java)
   at android.graphics.Bitmap.createBitmap(Bitmap.java:831)
   at android.graphics.Bitmap.createBitmap(Bitmap.java:808)
   at android.graphics.Bitmap.createBitmap(Bitmap.java:775)
   at maps.aa.g.a(Unknown Source)
   at maps.aa.i.a(Unknown Source)
   at maps.aa.i.a(Unknown Source)
   at maps.aa.i.b(Unknown Source)
   at maps.ac.o.a(Unknown Source)
   at maps.ac.t.a(Unknown Source)
   at maps.X.K.a(Unknown Source)
   at maps.X.H.a(Unknown Source)
   at maps.X.H.b(Unknown Source)
   at maps.X.y$f.f(Unknown Source)
   at maps.X.y$f.run(Unknown Source)

从这个堆栈跟踪中,我无法弄清楚崩溃发生的时间或原因。

我在应用程序的两个不同位置使用位图。这些是我的方法。

加载可绘制对象,然后在其上绘制一些文本:

public Bitmap getMarkerBitmap(Context context) {
    Resources resources = context.getResources();
    float scale = resources.getDisplayMetrics().density;
    Bitmap bitmap = null;
    Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    String text = Integer.toString(reservableCars);
    paint.setColor(Color.WHITE);

    if (reservableCars == 0) {
        bitmap = BitmapFactory.decodeResource(resources, R.drawable.marker_nocars);
    } else if (isPublic()) {
        bitmap = BitmapFactory.decodeResource(resources, R.drawable.marker_public_location_cars);
    } else {
        bitmap = BitmapFactory.decodeResource(resources, R.drawable.marker_corpo_location_cars);
    }

    android.graphics.Bitmap.Config bitmapConfig =
            bitmap.getConfig();
    // set default bitmap config if none
    if(bitmapConfig == null) {
        bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
    }
    // resource bitmaps are imutable,
    // so we need to convert it to mutable one
    bitmap = bitmap.copy(bitmapConfig, true);

    Canvas canvas = new Canvas(bitmap);
    // text size in pixels
    paint.setTextSize((int) (10 * scale));
    // text shadow
    paint.setShadowLayer(1f, 0f, 1f, Color.WHITE);

    // draw text to the Canvas center
    Rect bounds = new Rect();
    paint.getTextBounds(text, 0, text.length(), bounds);
    int x = (bitmap.getWidth() - bounds.width())/2;
    int y = (bitmap.getHeight() + bounds.height())/2;

    canvas.drawText(text, x, y, paint);

    return bitmap;
}

画一个圆圈和里面的两个字母。

public Bitmap drawProfileBitmap(Context context) {
    Paint paint = new Paint();
    Paint circlePaint = new Paint();
    Rect bounds = new Rect();
    String text = Character.toString(firstName.charAt(0)) + Character.toString(lastName.charAt(0));
    int pixelvalue = (int) (70 * context.getResources().getDisplayMetrics().density * 0.5f);
    Bitmap bitmap = Bitmap.createBitmap(pixelvalue, pixelvalue, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);

    paint.setColor(Color.WHITE);
    paint.setTextSize(40f);
    paint.setAntiAlias(true);
    paint.setTextAlign(Paint.Align.CENTER);
    paint.getTextBounds(text, 0, text.length(), bounds);

    circlePaint.setColor(context.getResources().getColor(R.color.primary));
    circlePaint.setAntiAlias(true);

    canvas.drawCircle(bitmap.getWidth()/2, bitmap.getHeight()/2, bitmap.getHeight(), circlePaint);
    canvas.drawText(text, bitmap.getWidth()/2, (bitmap.getHeight() + bounds.height())/2, paint);
    return bitmap;
}

会不会是上述方法之一导致的崩溃?第一个被多次调用。对于在 Google 地图上绘制的每个标记 - 但地图上的标记永远不会超过 15-20 个。

第二个在每次应用启动时只调用一次。

尝试回收不使用的位图

if ( mBitmap != null ) mBitmap.recycle();  
     mBitmap  = null; 

另外(如果可能的话),您需要删除指向您的位图的所有链接。 例如,如果使用图像视图:mImageView.setImageBitmap(null);等等