=================================
=================================
=================================
출처: http://www.androidside.com/bbs/board.php?bo_table=B49&wr_id=52563
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
위와같은 메모리 오버플로우 현상이 발생했습니다.
프로그램은 대략
터치를 했다가 놓음과 동시에 멀티쓰레드로 bitmap형태의 맵을 canvas에 뿌려서 draw해주는 프로그램입니다.
헌데 문제는 미친듯이 맵을 터치하면 위 빨간 에러가 팡~ 하며 나타나면서
메모리 누수문제로 프로그램이 닫히게 됩니다.
휴.. 누수되는 부분의 쇄스는
mImgBuffer = Bitmap.createBitmap(iWidth, iHeight, Bitmap.Config.ARGB_8888);
이곳일거라 판단됩니다. 계속해서 create를 해주니 문제가 되는듯한데
inpustream으로 이미지를 받아올때는
BitmapFactory.Options option = new BitmapFactory.Options();
option.inSampleSize = 1;
option.inPurgeable = true;
option.inDither = true;
Bitmap mImg = BitmapFactory.decodeStream(is, null , option);;
이와같은 방법으로 해결이 가능하다 inputStream이 아닐경우는 어찌 해야할지 난감하네요..
제가 임의로 mImgBuffer.recycle()을 해주게 되면 이또한 문제가 됩니다.
저 비트맵 이미지는 계속해서 사용해야 하기 때문이죠..
혹시 해결의 실마리를 아신다면 제공 부탁드려요 ^ㅠ^
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
이미지를 받으셔서 resize를 통해 크기를 좀 줄여주시고
다 쓴 이미지들은 recycle()을 통해 해제시켜주시면 좀 나아지실듯해요
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
근본적인 방법은 아닌데 일단 멀티 터치를 받아서 처리할때
연속 누름을 방지 하세요
미친듯이 이벤트처리를 다 요청 하는 어플은 아무도 만들지 않습니다
눈에 안보이는 시간 딜레이를 주는 거죠
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
기본적으로 이 프로그램에 요청에 의한 모든 조작이 끝나기 전에는 입력자체를 받지 않도록 해두었었는데..
요청을 안받아버리면 곤란하니까..
기술자님께서 말씀주신대로 일정한 초안에 일정한 횟수이상의 요청이 들어오면 이를 무시하도록 만들어야 겠네요..
리사이즈 리사이클은 사용해봤으나 생각처럼 되질 않아서.. ㅠㅠ 우선적으론 기술자님말씀대로 해놓아야겠네요 답변 감사합니다. ^^
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
이게 기초를 잘몰라서 생기는 문제라고 생각합니다.
우선 안드로이드의 BitmapFactory클래스는 JNI를 이용해서 native code로 이미지를 만들게 되어 있습니다.
그렇기 떄문에 decodedResource라는 메소드를 호출할때 달빅(JVM)에서 GC를 수행될수가 없습니다.
그러니 구글에서 제안하는 내용은 아시겠지만 option사용 안쓰는 리소스는 꼭 recycle해주라고 되어 있죠
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
=================================
=================================
=================================
ListView의 성능개선을 해보자.
프로그래밍/Java / Android 2010/05/18 17:24 |
Android의 위젯중 가장많이 사용한다고 해도 과언이 아닌 위젯이 ListView이다.
그 ListView를 활용하는대에 성능개선을 해보려고 한다.
ListView ?
ListView는 Android내에 있는 View중에 하나로서 ViewGroup으로 형성이 되어있다.
ViewGroup은 말그대로 View의 집합이라고 볼수 있다. 그만큼 많은 View들이 생성이 될수록 성능에 대해서 고려를 해봐야되는게 정상이다. 그래서 ListView에 ViewGroup을 컨트롤을 하고 정의하는 Adapter 객체를 성능고려를 하여서 작성하는법에 대해 알아보겠습니다.
성능고려 코딩에 앞서 기본적인 Adapter의 성능에 대한 객체 생성법을 3가지로 나누워서 설명을 해보겠습니다.
1. 기본적인 생성법
public class ItemAdapter extends ArrayAdapter<string> { final Activity context; ItemAdapter(Activity context, ArrayList<string> list) { super(context, R.layout.listrow, list); this.context = context; } public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = context.getLayoutInflater(); View row = inflater.inflate(R.layout.listrow, null); TextView label = (TextView)row.findViewById(R.id.label); label.setText(getItem(position)); return row; } } </string></string> |
getView메소드는 각 View가 보여질때마다 호출이 된다.
그래서 getView에서 각각의 View들을 컨트롤을 하고 정의를 해야한다.
여기서 중요한게 Inflater라는 객체 이다. Inflater는 XML 레이아웃에 정의된 내용을 분석해서 View의 객체트리구조로 만드는 역활을 하고 있다.
이제 생성이 된 View단에 findViewById를 이용하여 TextView를 생성하고 getItem메소드를 사용해서 TextView에 셋팅을 해주고 있다.
* getItem 메소드는 ArrayAdapter의 Memeber Method로서 생성자에서 셋팅한 배열을 position를 이용하여 불러와주는 역할을 한다.
2. convertView 활용
public class ItemAdapter extends ArrayAdapter<string> { final Activity context; ItemAdapter(Activity context, ArrayList<string> list) { super(context, R.layout.listrow, list); this.context = context; } public View getView(int position, View convertView, ViewGroup parent) { View row = convertView; if (row == null) { LayoutInflater inflater = context.getLayoutInflater(); row = inflater.inflate(R.layout.listrow, null); } TextView label = (TextView)row.findViewById(R.id.label); label.setText(getItem(position)); return row; } } </string></string> |
2번째 방법으로는 covertView를 사용하여 View객체 생성을 줄이는것이다.
처음 getView가 호출이 되면 convertView는 null값이 들어가는데 그 이후로는 null값이 들어가지 않는다.
이점을 생각해보니 View에 Inflater이 생성을 줄이기 위해 재귀호출 형식으로 리턴 된 VIew를 넣어주는것같다.
그럼 위와 같이 코딩을 하면 만약 10개의 아이템을 가진 list를 출력하고자 하면 10번의 inflater의 생성을 방지할수 있게 되는것이다. 이것이 10번이라면 많은 성능이 차이가 나지 않겠지만 점점 많아진다고 하면 엄청난 View단의 객체 생성 자원을 절약할수 있게된다.
여기서 ListView의 성능개선법이 끝이아니고 마지막으로 Adapter를 생성할때의 가장좋은 효과를 볼수 있는 홀더 패턴을 이용하여서 코딩을 해보겠다.
3. 홀더패턴
2번의 코딩법도 1번의 코딩법에 대해서 엄청난 성능의 효과를 볼수 있엇는데 2번의 코딩법중 findViewById라는 메소드도 엄청난 성능을 떨어지게 한다.
findViewById 메소드는 인플레이션으로 생성한 위젯 가운데 ID를 이용하여 찾아오는 기능을 하는데 위젯 내부의 객체 트리에서 원하는 객체를 찾는데 필요한 연산의 양은 무시하지 못할수준이다. 그래서 이것을 적용하기 위해 객체를 하나 생성을 해서 View에서 제공하는 setTag와 getTag를 이용하여 findViewById의 호출을 절약해보겟다.
public class ItemAdapter extends ArrayAdapter<string> { final Activity context; ItemAdapter(Activity context, ArrayList<string> list) { super(context, R.layout.listrow, list); this.context = context; } public View getView(int position, View convertView, ViewGroup parent) { View row = convertView; ItemWrapper wrapper; if (row == null) { LayoutInflater inflater = context.getLayoutInflater(); row = inflater.inflate(R.layout.listrow, null); wrapper = new ItemWrapper(row); row.setTag(row); } else { wrapper = (ItemWrapper)row.getTag(); } wrapper.getTextView().setText(getItem(position); return row; } class ItemWrapper { View base; TextView label; ItemWrapper(View base) { this.base = base; } TextView getTextView() { if (label == null) label = (TextView)base.findViewById(R.id.label); return label; } } </string></string> |
ItemWrapper라는 클래스를 만들어서 View에 tag메소드를 이용하여 처리를 하니 엄청난 자원을 절약을 할수 있게된다.
이렇게 3가지의 유형으로 Adapter를 생성을 알아봤는데 1번과 3번은 데이터의 양이 많아 질수록 성능에 대한 차이를 눈으로 확인을 할수 있게 될것이다. 하지만 데이터의 양이 많지 않은곳은 굳이 코딩이 더 길어지는 홀더패턴을 이용하여 처리를 안해도 될듯하다. 하지만 확실히 데이터양이 많아지면 차이가 난다는거 !
참고자료 : 알짜만 골라 배우는 안드로이드 프로그래밍 서적
=================================
=================================
=================================
'스마트기기개발관련 > 안드로이드 개발' 카테고리의 다른 글
안드로이드 ImageButton 클릭시 이미지를 변경 해보자 (0) | 2020.09.19 |
---|---|
안드로이드 이미지 리소스 관련~ (0) | 2020.09.18 |
안드로이드 Dialog창에 테두리 없애기, 투명도 주기,배경투명도, 꾸미기 관련 (AlertDialog, popup, Dialog 등등 (0) | 2020.09.18 |
안드로이드 개발 portrait & landscape 처리, 화면 회전 관련 (0) | 2020.09.18 |
안드로이드 플레그먼트 레이아웃 관련 (0) | 2020.09.18 |