2016-10-07 3 views
3

So sehe ich in Crashlytics haben wir einige Abstürze von OOM mit Bitmaps verursacht. Scheint, 60% von ihnen kommen von Galaxy S7 Edge-Geräten auf 6.0.1. Was wir haben, ist ein Landing-Bildschirm mit 2 Bildern, ein Hintergrundbild, das von rechts nach links gescrollt und dann neu erstellt wird, um ihnen den Eindruck der Bewegung zum Vordergrundbild zu geben.Android OOM mit Bitmap

Am Anfang des Fabric-Logs steht, dass es einen Fehler beim Aufblasen der Klasse gibt. Allerdings weiter unten im Stapel, ich sehe es scheint von unserem ParallaxImageView verursacht werden. In wir hier tun:

private void initializeCustomAttrs(Context context, AttributeSet attrs) { 
    TypedArray attributes = context.getTheme().obtainStyledAttributes(
      attrs, 
      R.styleable.ParallaxImageView, 
      0, 0); 

    try { 
     speed = attributes.getDimension(R.styleable.ParallaxImageView_speed, 10); 
     bitmap = BitmapFactory.decodeResource(getContext().getResources(), 
       attributes.getResourceId(R.styleable.ParallaxImageView_src, 0)); 

    } finally { 
     attributes.recycle(); 
    } 
} 

Ich bin nicht sicher, ob dies richtig ist, wo es passiert, oder wenn eine der anderen Methoden dazu führen könnte. Wir haben auch diese Methoden:

@Override 
public void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 

    if (canvas == null || bitmap == null) { 
     return; 
    } 

    canvas.getClipBounds(clipBounds); 

    while (offset <= -bitmap.getWidth()) { 
     offset += bitmap.getWidth(); 
    } 

    float left = offset; 
    while (left < clipBounds.width()) { 
     int width = bitmap.getWidth(); 
     canvas.drawBitmap(bitmap, getBitmapLeft(width, left), 0, null); 
     left += width; 
    } 

    if (isAnimating && speed != 0) { 
     offset -= abs(speed); 
     postInvalidateOnAnimation(); 
    } 
} 

@Override 
public void onAttachedToWindow() { 
    super.onAttachedToWindow(); 
    start(); 
} 

@Override 
public void start() { 
    if (!isAnimating) { 
     isAnimating = true; 
     postInvalidateOnAnimation(); 
    } 
} 

@Override 
public void stop() { 
    if (isAnimating) { 
     isAnimating = false; 
     invalidate(); 
    } 
} 

private Bitmap scaleToFitHeight(Bitmap bitmap, int height) { 
    if (height > 0) { 
     float factor = height/(float) bitmap.getHeight(); 

     Bitmap newBitmap = Bitmap.createScaledBitmap(bitmap, (int) (bitmap.getWidth() * factor), height, true); 
     if (!newBitmap.equals(bitmap)) { 
      bitmap.recycle(); 
     } 

     return newBitmap; 
    } 
    return bitmap; 
} 

private float getBitmapLeft(float layerWidth, float left) { 
    if (speed < 0) { 
     return clipBounds.width() - layerWidth - left; 
    } else { 
     return left; 
    } 
} 

Ich habe keine Ahnung, was dieses Problem verursachen könnte, wie ich denke, wir sind Decodierung und Recycling richtig. Ich bin mir nicht sicher, ob es etwas speziell auf 6.0.1 sein könnte, das es verursacht, aber jede Hilfe hier würde sehr geschätzt werden. Danke

+0

Können Sie die Protokolle auch veröffentlichen? – petey

Antwort

0

Sie entschlüsseln das Bild nicht richtig, Sie sollten zuerst die Größe überprüfen und dann mit einem Skalierungsfaktor dekodieren. Lassen Sie uns sagen, Ihr Bild ist 2000 x 2000, könnte die komprimierte Version leicht < 1mb aber Dekomprimierung in eine Bitmap würde 2000 * 2000 * 4 Bytes = 16 MB (!)
es möglicherweise nicht der Fall sein, wenn Sie sicher sind, dass das Bild Größe ist überschaubar, aber da Sie OOM bekommen Ich denke, es ist nicht

siehe here für Implementierungsdetails