I have a very simple Activity
that draws a drawable on another drawable in a Canvas
and in the end shows it on a ImageView
. I know that creating bitmaps takes too much memory and scale them down and I know about leaking by keeping reference to context, but can not detect where it happens. by now after 4-5 times rotating I get out of memory error. (I've specified that on code)
Can you help me find where leak happens?
here is my code:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int height = displaymetrics.heightPixels;
int width = displaymetrics.widthPixels;
// image view in main layout to be filled by raw bitmaps combination
ImageView imageView = (ImageView) findViewById(R.id.image);
// Get your images from their files
// raw bitmaps taken from drawable folder
//Bitmap bottomImage = BitmapFactory.decodeResource(getResources(), R.drawable.arsenal);
//Bitmap topImage = BitmapFactory.decodeResource(getResources(), R.drawable.setare);
Log.v("imageView", String.valueOf(imageView.getWidth()) + " " + imageView.getHeight());
Bitmap bottomImage = decodeSampledBitmapFromResource(getResources(),
R.drawable.arsenal, width, (int)0.75 * width);
Bitmap topImage = decodeSampledBitmapFromResource(getResources(),
R.drawable.setare, 400, 400);
// a copy of the below bitmap that is mutable.
Bitmap temp = bottomImage.copy(Bitmap.Config.ARGB_8888, true); /// ?! I get error here!
// not necessary, only for testing whether is possible to diractly cache a text view or not
TextView t = (TextView) findViewById(R.id.text);
t.setDrawingCacheEnabled(true);
// canvas for drawing functions
Canvas comboImage = new Canvas(temp);
// Then draw the second on top of that
comboImage.drawBitmap(topImage, 400f, 400f, null);
// a paint to determine style of what would be drawn in canvas.
Paint p = new Paint();
p.setColor(Color.YELLOW);
p.setStyle(Style.FILL);
p.setTextSize(70);
// manually draw a text on canvas
comboImage.drawText("Ehsan Mirza Razi", 100, 100, p);
// draw text view directly on canvas.
//by now causes out of memory exception
//comboImage.drawBitmap(t.getDrawingCache(), 1000f, 200f, new Paint());
// drawing the temp drawable edited in canvas, on ImageView
imageView.setImageDrawable(new BitmapDrawable(getResources(), temp));
// To write the file out to the SDCard:
OutputStream os = null;
try {
os = new FileOutputStream("myNewFileName.png");
bottomImage.compress(CompressFormat.PNG, 100, os);
topImage.recycle();
bottomImage.recycle();
temp.recycle();
} catch(IOException e) {
e.printStackTrace();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
public static 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;
if (height > reqHeight || width > reqWidth) {
// Calculate ratios of height and width to requested height and width
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
Log.v("shrink", String.valueOf(inSampleSize));
return inSampleSize;
}
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
//ImageView = null;
}
}