마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

bitmap 이미지를 다량으로 쓰려는데 메모리 관리를 어떻게 해야할까요?

0 추천

안드로이드 개발 시작한지 사흘 된 초보입니다.

drawable에서 bitmap 변수로 이미지를 받고 화면에 올리려고 하는데, 파일이 많습니다.

현재는 일단 아래와 같이 작성하였습니다

 

			BitmapDrawable bd2 = (BitmapDrawable)getDrawable(R.drawable.bg_2);
			Bitmap image2 = bd2.getBitmap();
			BitmapDrawable bd3 = (BitmapDrawable)getDrawable(R.drawable.bg_wave_1);
			Bitmap image3 = bd3.getBitmap();
			BitmapDrawable bd4 = (BitmapDrawable)getDrawable(R.drawable.bg_wave_2);
			Bitmap image4 = bd4.getBitmap();
			BitmapDrawable bd5 = (BitmapDrawable)getDrawable(R.drawable.bg_wave_3);
			Bitmap image5 = bd5.getBitmap();
			BitmapDrawable bd6 = (BitmapDrawable)getDrawable(R.drawable.bg_wave_4);
			Bitmap image6 = bd6.getBitmap();
			BitmapDrawable bd7 = (BitmapDrawable)getDrawable(R.drawable.bg_wave_5);
			Bitmap image7 = bd7.getBitmap();
			BitmapDrawable bd8 = (BitmapDrawable)getDrawable(R.drawable.bg_wave_6);
			Bitmap image8 = bd8.getBitmap();
			BitmapDrawable bd9 = (BitmapDrawable)getDrawable(R.drawable.bg_wave_7);
			Bitmap image9 = bd9.getBitmap();
			BitmapDrawable bd10 = (BitmapDrawable)getDrawable(R.drawable.bg_wave_8);
			Bitmap image10 = bd10.getBitmap();
			BitmapDrawable bd11 = (BitmapDrawable)getDrawable(R.drawable.image1_nor);
			Bitmap image11 = bd11.getBitmap();

...


			canvas.drawBitmap(image1, new Rect(0,0,image1.getWidth(),image1.getHeight()), new Rect(0,0,180,canH), null);
			canvas.drawBitmap(image2, new Rect(0,0,image2.getWidth(),image2.getHeight()), new Rect(180,0,canW-180,canH), null);
			canvas.drawBitmap(image1, new Rect(0,0,image1.getWidth(),image1.getHeight()), new Rect(canW-180,0,canW,canH), null);
			canvas.drawBitmap(image3, new Rect(0,0,image3.getWidth(),image3.getHeight()), new Rect(0,556*2,320,556*2+134*2), null);
			canvas.drawBitmap(image4, new Rect(0,0,image4.getWidth(),image4.getHeight()), new Rect(320,556*2,640,556*2+134*2), null);
			canvas.drawBitmap(image5, new Rect(0,0,image5.getWidth(),image5.getHeight()), new Rect(640,556*2,960,556*2+134*2), null);
			canvas.drawBitmap(image6, new Rect(0,0,image6.getWidth(),image6.getHeight()), new Rect(960,556*2,1280,556*2+134*2), null);
			canvas.drawBitmap(image7, new Rect(0,0,image7.getWidth(),image7.getHeight()), new Rect(1280,556*2,1600,556*2+134*2), null);
			canvas.drawBitmap(image8, new Rect(0,0,image8.getWidth(),image8.getHeight()), new Rect(1600,556*2,1920,556*2+134*2), null);
			canvas.drawBitmap(image9, new Rect(0,0,image9.getWidth(),image9.getHeight()), new Rect(1920,556*2,2240,556*2+134*2), null);
			canvas.drawBitmap(image10, new Rect(0,0,image10.getWidth(),image10.getHeight()), new Rect(2240,556*2,2560,556*2+134*2), null);

....

보기만 해도 암걸리는 그런 코드인데...ㅠ 한 화면에 이와 같이 bitmap 그림을 몇십개씩 뿌리려고 할 때 이렇게 메모리를 왕창 쓰지 않고자 한다면 어떤 식으로 해야할지 궁금합니다.

또한 저 이미지 중 일부를 이미지버튼처럼 사용하고자 하는데 이 경우에는 위와 같이 drawBitmap 같은 함수를 사용하면 안되는건가요? 아예 다른 방식으로 접근해야하는지 궁금합니다.

삶은젤리 (140 포인트) 님이 2015년 9월 2일 질문

2개의 답변

0 추천

단순히 파일이 많은 것만 가지고 판단할 문제는 아닌것 같은데요. 

- 타겟 안드로이드 버전이 얼마인지

- Bitmap 이미지의 용량이 정말 큰 것인지의 여부

- Bitmap 이 계속 재사용되는지의 여부

등에 따라서 처리하시면될것 같습니다. 우선 안드로이드 스튜디오에서 HeapMemory가 어떻게 사용되고 확인하세요. 

각 비트맵 파일크기가 별로 크지 않다라고 하면 어차피 canvas에 그린후 각 bitmap 은 알아서 GC될것이니 무시하셔도 될것이구요.

실제 OutOfMemoryError가 발생할 정도의 크기다라고 한다면 Canvas에 그리고 바로바로 recycle해버리는 방법이 있을것 같습니다. 위 코드 보면 image1말고는 재활용되지 않네요.

BitmapDrawable bd2 = (BitmapDrawable)getDrawable(R.drawable.bg_2);
Bitmap image2 = bd2.getBitmap();
canvas.drawBitmap(image2, new Rect(0,0,image2.getWidth(),image2.getHeight()), new Rect(180,0,canW-180,canH), null);
image2.recycle();
image2 = null;
BitmapDrawable bd3 = (BitmapDrawable)getDrawable(R.drawable.bg_wave_1);
Bitmap image3 = bd3.getBitmap();
canvas.drawBitmap(image3, new Rect(0,0,image3.getWidth(),image3.getHeight()), new Rect(0,556*2,320,556*2+134*2), null);
image3.recycle();
image3 = null;
위와 같이 했을때 정말 차이가 있는지 HeapMemory변화 관찰해보시기 바랍니다.
 
자세한건 아래 문서 참고하시면 됩니다.
 
회색 (21,420 포인트) 님이 2015년 9월 2일 답변
비트맵 선언을 계속 하다보니 그 때문에 뭔가 문제가 생기지 않을까 걱정했었는데 생각해보니 이미지 크기가 중요하지 변수 몇개 선언했나 이런거는 별 문제가 되지 않겠군요... ㅎㅎ
일단 bitmap의 크기가 하나에 수십 kb 정도라 지금은 지나가고, 나중에 문제가 발생하거나 하면 그때 다시 체크할 예정입니다. 그런데 혹시라도 나중에 heap memory를 확인하게 된다면, 어디서 확인할 수 있나요? 현재 이클립스 사용해서 개발하고 있습니다.
0 추천
뭘 하시려는지는 모르겠지만,

캔버스에 비트맵으로 가져와서 때려넣는건 필요없어 보입니다.

그냥 xml상에서 배치하세요. 버튼으로 사용 할 예정이라면 더더욱.
익명사용자 님이 2015년 9월 2일 답변
xml보다 자바쪽이 익숙해서 일단 그렇게 작성하였는데, 찬찬히 찾아보니 확실히 xml에서 배치하는 쪽이 나은 듯 하네요. 조언 감사합니다.
...