안규 공부방

Android > listview - Adapter.getView의 성능 높이기 - ViewHolder 를 사용하라

등록일 : 2017-07-05 18:49 조회수 : 93,867

Android에서 ListView라 들어있는 페이지가 열릴때 다른페이지에 비해서 많이 느리게 뜨는 경우가 있습니다.

궁금해서 Adapter의 getView()쪽에 로그를 찍어봤더니. adapter에 전달한 data의 개수 * 3번의 호출이 일어나고 있었습니다.

구글신이 아래의 포스트를 던져주셨습니다.;;

참고 : 안드로이드 ListView구현시 Adapter의 getView 중복 호출 문제

즉, layout를 정의한 xml에서 ListView와 감싸고 있는 Layout의 layout_height / layout_width를 match_parent로 변경하라! 라는 내용이었습니다.

attribute를 수정하니까 잘되네요.

그밖에도 ListView의 성능관련 이슈와 관련된 포스팅도 몇가지 발견해서 정리해둡니다.
 
		......
		@Override
		public View getView (int position, View convertView, ViewGroup parent) {
			View view = convertView;
			if (view == null) { 
				view = mInflater.inflate(resource, null);
			}
			
			((ImageView)view.findViewById(R.id.book_image)).setImageBitmap(getBitmap(getItem(position).getCover()));
			((TextView)view.findViewById(R.id.title)).setText(getItem(position).getTitle());
			((TextView)view.findViewById(R.id.author)).setText(getItem(position).getAuthor());
			((TextView)view.findViewById(R.id.publisher)).setText(getItem(position).getPublisher());
			//Log.d(TAG, "position = " + position + ", publisher = " + getItem(position).getPublisher());
			// 이 윗줄의 코드의 로그를 보니 각 position 값이 3번씩 찍히고 있더군요....;
			return view;
		}
		......


중요 포인트는 getView()에 넘어오는 convertView가 null일때 inflate 해줘라. 라는 것입니다.

이유는 ListView가 6~7개의 정도 ListView 내부에 표시될 view를 캐시해서 recycle하는 방식으로 움직이기 때문이라는군요.

즉, recycle 된 객체가 넘어올 경우 inflate 할 필요없이 내용만 바꿔서 return 하면 된다는거지요.

그밖에도 참고한 블로그에는 “ViewHolder”를 사용해서 findViewById()의 횟수를 줄이는 방법도 있었습니다.

recycle되니까 view가 null이 아닐경우 다시 find하지 않고 setTag() / getTag()를 이용해 ViewHolder를 view에

넣어두고 재사용하는 방식입니다.

위 코드에 적용하면 아래처럼 됩니다.
		@Override
		public View getView (int position, View convertView, ViewGroup parent) {
			View view = convertView;
			ViewHolder holder;
			if (view == null) { 
				view = mInflater.inflate(resource, null);
				holder = new ViewHolder();
				
				holder.bookImage = (ImageView)view.findViewById(R.id.book_image);
				holder.title = (TextView)view.findViewById(R.id.title);
				holder.author = (TextView)view.findViewById(R.id.author);
				holder.publish = (TextView)view.findViewById(R.id.publisher);
				
				view.setTag(holder);
			} else {
				holder = (ViewHolder) view.getTag();
			}
			
			holder.bookImage.setImageBitmap(getBitmap(getItem(position).getCover()));
			holder.title.setText(getItem(position).getTitle());
			holder.author.setText(getItem(position).getAuthor());
			holder.publish.setText(getItem(position).getPublisher());
			
			return view;
		}

		static class ViewHolder {
			ImageView bookImage;
			TextView title;
			TextView author;
			TextView publish;
		}
		
 
※ 혹시 도움이 되셨다면 댓글에 한마디 남겨주세요!
작성자   비밀번호
자동글 방지     (자동글 방지 기능입니다.)
내용   댓글달기 
이메일 문의 : cak0280@nate.com  
Copyright 2000 By ENTERSOFT.KR All Rights Reserved.