Reputation:
I'm trying to pinpoint this memory leak.
I have two SurfaceViews
, A
and B
. I start A
, then navigate to B
, then press the back button to go back to A
, and then I navigate to B
again.
I can see my allocated memory rise each time I do this, and eventually I'll get an out of memory error.
Here is how I navigate to B
, from inside the SurfaceView
connected to A
Context context = this.getContext();
Intent i =new Intent(context, StartCareer.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(i);
In both views, I have a lot of Bitmaps drawing. In B
, I can't find any references to A
, and the only reference outside the context that I can think of is a reference to a Global class that I have. I also have some analytics stuff going on in the background. It could be a million different things, I'd imagine
I have the DDMS view on Eclipse up, but I'm not sure what I'm looking at, or how to find the exact object that keeps getting repeated.
I'd accept either a crash-course/tutorial on the DDMS Allocation Tracker, or someone to point out what I'm doing wrong.
Additional information:
I have some bitmaps being drawn on a SurfaceView
. Examples of such from B
are:
////At class level
Bitmap rightB,leftB;
////In the constructor
rightB = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.right), 100,75, true);
////In doDraw
canvas.drawBitmap(rightB, rbX, rbY, null);
And my onDestroys
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mThread.isAlive()){
mThread.setMenuRunning(false);
}
}
So I've run MAT and found one leak, at least. My Thread
Keeps getting recreated.
Here's what's doing it.
@Override
public void surfaceCreated(SurfaceHolder holder) {
loading=false;
if (!mThread.isAlive()){
mThread = new ViewThread(this);
mThread.setMenuRunning(true);
mThread.start();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mThread.isAlive()){
mThread.setMenuRunning(false);
}
}
Assuming that these methods get called every time the view loses or gains focus, this seems obviously wrong. How can I re-organize this so that it's not?
Upvotes: 5
Views: 4953
Reputation: 913
Call this method in onDestroy()
and onstop()
of your app.
private void unbindDrawables(View view) {
Log.d(TAG,"in unbindDrawables");
if (view.getBackground() != null) {
view.getBackground().setCallback(null);
}
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
unbindDrawables(((ViewGroup) view).getChildAt(i));
}
((ViewGroup) view).removeAllViews();
view.setBackgroundResource(0);
Log.d(TAG,"removed views");
//finish();
}
}
Upvotes: 4
Reputation: 9574
What you need to do is explained in detail here. For your specific issue, you need to do this
// resize to desired dimensions
int height = b.getHeight();
int width = b.getWidth();
Log.d(TAG, "1th scale operation dimenions - width: " + width + ",
height: " + height);
double y = Math.sqrt(IMAGE_MAX_SIZE
/ (((double) width) / height));
double x = (y / height) * width;
Bitmap scaledBitmap = Bitmap.createScaledBitmap(b, (int) x,
(int) y, true);
b.recycle();
Upvotes: 0
Reputation: 28541
A few hints:
Upvotes: 3
Reputation: 4119
Try to recycle() your bitmaps in onDestroy() of your activities.
Upvotes: 1