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

 

대부분의 안드로이드 관련 책을 보면 ListView를 구현시에 Row를 캐시하는것에 대해 언급이 되어있습니다. 하지만 ViewHolder를 쓰는 방법에 대해서는 언급된 책이 별로 없더군요. 저도 지난번 안드로이드 개발자랩에 가서 이것의 존재를 알게 되었습니다;;

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

위에서 ViewHolder를 구현한 부분은 getView하나만 보시면 됩니다. 생성된 viewHolder의 경우 다음과 같이 전체가 public으로 구현된 간단한 클래스 하나면 됩니다.

여기서 조금 특이한 점은 대부분이 맴버변수는 private으로 선언한 뒤에 getter/setter를 사용하는 방식을 취하지 않고 맴버변수에 직접적으로 접근을 한다는 점입니다. [이글]을 참고해보시면 메서드내에서 맴버변수(필드)에 접근하는것조차 상대적으로 비용이 크다는 언급이 나옵니다.

결론적으로 실행에 드는 비용을 줄일려고 ViewHolder를 사용하므로 ViewHolder내에서도 메서드 호출의 숫자까지 줄이는것이 중요해 보입니다. 결론적으로 viewHolder에서 Row내의 요소 위젯들을 직접적으로 가지고 있으므로 바로바로 값을 변경할 수 있습니다.

실제로 안드로이드 개발자랩에서 보여준 데모에서는 많은 Row를 가진 ListView라도 매우 빠르게 동작하더군요.

  • 어울려사는세상

    정말 좋은 정보네요.. 감사합니다.
    퍼가겠습니다.^^

  • 연_

    질문하나 드리겠습니다. ForStudyAdapter메소드의

    인자중에 Context와 layout의 의미가 궁금합니다. 그리고

    지금 SAX파싱 연습중인데 이 예제를 어답터에 적용하니까

    어답터와 어레이리스트를 연결하는 부분에서 에러가 나더

    군요 연결부에 메소드에 들어간 인자를 동일하게 넣어주면

    또다른 에러가 나면서 변수나 메서드를 만들겠냐는 힌트가 뜹니다. 인자의 의미와 실제로 어답터와 리스트를 연결할때가 궁금하네요

  • 연_

    질문글 달고 자답이네요 ㅡㅡ; 해당 인자를 전역변수로 선언해놓으니까 되네요 ㅎㅎㅎ;;;

  • 연_

    그런데 텍스트뷰로 리스트내용을 출력하는데 한쪽에 TextView라고 계속 출력되네요 ㅡㅡ; 이건 천천히 해결해야 할듯 싶습니당 ㅋ;

  • 리게임

    좋은설명 감사합니다.. 정말 뷰홀더에 대한 설명이 너무 적었습니다. 감사합니다.

  • 질문하는자!

    질문이 있습니다. getName,getAddress를 person클래스에서 가져오는데 이게 가능할려면 person 클래스에서 어떻게 해야하죠?

  • 초보

    오 내용 감사합니다
    찾고 있는 내용이 딱있네요
    아직 안드로이드 입문단계인데 많은 도움이 됬습니다 ㅎ

  • holyreign

    뷰홀더를 재사용시 데이터가 뒤죽 박죽되거나

    해당 값에 맞지 않는 이미지, 레이아웃 등이

    눈앞에 펼쳐질 겁니다.

    물론 이론상과 간단한 예제에선 잘 되겠지만요…

    • 이상한 일이네요. 저는 지금까지 실무에 적용하면서 문제를 겪어보진 못했습니다.
      뷰홀더의 역할은 뷰의 재활용등이 아닌 단지 findViewById 호출을 줄이는데 의의가 있는것인데 말이죠. 어떤 문제가 있으셨는지 공유해 주실 수 있으실까요?

  • HongJinBom

    감사합니다~!