UroA 개발 블로그

[Android] ListView 구현시 뷰홀더(ViewHolder) 사용하기 본문

Programming/Android

[Android] ListView 구현시 뷰홀더(ViewHolder) 사용하기

UroA 2015. 11. 22. 11:01

ListView 구현시에 뷰홀더(ViewHolder) 사용하기

 

ViewHolder란, 이름 그대로 뷰들을 홀더에 꼽아놓듯이 보관하는 객체를 말합니다. 각각의 Row를 그려낼 때 그 안의 위젯들의 속성을 변경하기 위해 findViewById를 호출하는데 이것의 비용이 큰것을 줄이기 위해 사용되는 패턴입니다.

ViewHolder는 주로 ListView의 퍼포먼스를 높이기 위하여 사용됩니다.

 

Android 개발자 공식 홈페이지에서도 소개되어 있습니다.

http://developer.android.com/training/improving-layouts/smooth-scrolling.html#ViewHolder

 

ViewHolder를 사용하기전에 ListView의 구조부터 알아야합니다.

ListView는 내부에서 화면에 보여질 뷰 배열을 몇개만 생성하고 스크롤 되었을때 이것을 재활용합니다. (Grid View도 마찬가지)

 

위의 뷰들은 Adapter Class의 getView의 2번째 인자인 convertView로 넘어오게 됩니다.

이 convertView는 최초 한번만 생성되므로 최초로 호출되는 getView의 convertView는 null값으로 넘어오게 되어 이 특성을 이용해서 convertView == null일때만 Layout을 inflate하고 findViewById()로 view를 ViewHolder에 저장해주고 이것을 다시 converView의 Tag에 저장해주고 다음 호출시에 converView != null 이기 때문에 이 처리부분에서 convertView의 저장된 Tag를 ViewHolder로 캐스팅하여 가져와 view를 바로 꺼내 사용하면 됩니다.

 

[View Holder 적용 전]

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    View v = convertView;
    if(v == null) {
        LayoutInflater inflater = LayoutInflater.from(mContext);
        v = inflater.inflate(R.layout.layout_list_item, null);
    }
    TextView txtName = (TextView)v.findViewById(R.id.txtName);
    TextView txtMail = (TextView)v.findViewById(R.id.txtMail);

    Contact entry = mList.get(position);
    txtName.setText(entry.getName());
    txtMail.setText(entry.getMail());

    return v;

}

ViewHolder 를 적용하기 전에는 항상 xml 리소스에 접근하게 되며 성능 저하의 원인이 된다.


 

[View Holder 적용 후] 

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    if(v == null) {
        LayoutInflater inflater = LayoutInflater.from(mContext);
        v = inflater.inflate(R.layout.layout_list_item, null);
        ViewHolder holder = new ViewHolder();
        holder.txtName = (TextView)v.findViewById(R.id.txtName);
        holder.txtMail = (TextView)v.findViewById(R.id.txtMail);
        v.setTag(holder);
    }
    Contact entry = mList.get(position);
    if(entry != null) {
        ViewHolder holder = (ViewHolder)v.getTag();
        holder.txtName.setText(entry.getName());
        holder.txtMail.setText(entry.getMail());
    }
    return v;
}

static class ViewHolder {
    TextView txtName;
    TextView txtMail;
}


이런식으로 ViewHolder 클래스를 만들고 처음 한번만 xml 리소스의 접근할 경우 getView 가 불릴때 마다 findViewByID 를 할 필요가 없어져 성능이 좋아집니다.


추가적으로 아래의 사이트를 참고하시면 더 도움이 될 것 입니다.

http://www.kmshack.kr/2014/08/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-ui%EC%B5%9C%EC%A0%81%ED%99%94-%EB%A6%AC%EC%8A%A4%ED%8A%B8%EB%B7%B0-%EC%84%B1%EB%8A%A5%EC%B5%9C%EC%A0%81%ED%99%94/


Comments