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;
}