添加到AnimationDrawable的图像以编程方式泄漏内存

时间:2011-10-05 08:52:04

标签: android memory-leaks

我有一个拥有大量动画的Android应用程序。

当我以编程方式创建动画时(使用AnimationDrawable),非java对象(如DDMS堆标签中所示)随着我加载的每个新动画而增长,即使在我加载后也不会缩小动画发布。

我对我编写的包装器对象中的每个AnimationDrawable对象只有一个引用,我通过覆盖finalize方法并确保它被调用来验证此对象是否被释放。

最终android停止加载图像并将“内存不足”错误打印到日志中。

有趣的是,这种情况只发生在某些设备(Motorola Xoom,Sony Experia)而其他设备(例如Galaxy S)中。

从我给出的设备示例中可以看出,这个问题不是特定的Honeycomb或pre-Honeycomb。

我尝试过的一些事情:

  1. 完成当前动画后,在每个帧上调用回收,但似乎没有帮助。
  2. 为AnimationDrawble对象分配null
  3. 确保没有与持有动画可绘制的引用的类相关的静态变量
  4. 在我发表评论myAnimation.addFrame(...)
  5. 后,请确保问题消失

2 个答案:

答案 0 :(得分:0)

这不是一个确切的答案,而是一个有用的提示,可以找到确切泄漏发生的位置。在您希望回收内存之后执行堆转储,并查看为什么您认为应该死的对象仍然存在。

确保获得eclipse的内存分析工具。 (http://www.eclipse.org/mat/)

答案 1 :(得分:0)

可能有两个可能的原因,首先是在创建位图时,第二个是在将位图转换为BitmapDrawable时。正如我从您的评论(new BitmapDrawable(currentFrameBitmap)中可以看到的,现在使用BitmapDrawable(getResources(),currentFrameBitmap)更好地折旧此方法如果没有参考资源,即使正确缩放,位图也可能无法正确呈现。要有效地加载位图,您可以正确地缩放它。

public class BitmapDecoderHelper {
private Context context;
public BitmapDecoderHelper(Context context){
    this.context = context;
}
public int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
Log.d("height reqheight width reqwidth", height+"//"+reqHeight+"//"+width+"///"+reqWidth);
if (height > reqHeight || width > reqWidth) {
    if (width > height) {
        inSampleSize = Math.round((float)height / (float)reqHeight);
    } else {
        inSampleSize = Math.round((float)width / (float)reqWidth);
    }
}
return inSampleSize;
}
public Bitmap decodeSampledBitmapFromResource(String filePath,
        int reqWidth, int reqHeight) {

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

    BitmapFactory.decodeFile(filePath, options);
    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    Log.d("options sample size", options.inSampleSize+"///");
    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    // out of memory occured easily need to catch and test the things.
    return BitmapFactory.decodeFile(filePath, options);
}
public int getPixels(int dimensions){
    Resources r = context.getResources();
    int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dimensions, r.getDisplayMetrics());
    return px;
}
public String getFilePath(Uri selectedImage){
    String[] filePathColumn = {MediaStore.Images.Media.DATA};
    Cursor cursor = context.getContentResolver().query(selectedImage, filePathColumn, null, null, null);
    cursor.moveToFirst();
    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
    String filePath = cursor.getString(columnIndex);
    cursor.close();
    return filePath;
}

}