ListView의 ViewHolder라는 개념에 대해서 알게 되었는데 제가 이해한 것이 맞는지 확인 부탁드립니다!


ListView와 관련된 키워드를 검색하던 도중 ViewHolder라는 것에 대해서 알게되어서 관련 블로그들을 읽고서 제가 이해한 것들을 적어보려고 하는데 맞는지 확인 부탁드립니다. 틀린 것이 있다면 알려주시면 감사하겠습니다!

일단 제가 어디선가 듣기로는(읽기로는?) ListView의 item이 엄청 많다고 했을 때, 디바이스(스마트폰 같은)의 메모리가 부족해질 수 있으니까 ListView의 adapter가 그 메모리를 자동으로 관리해주는 것으로 알고 있었습니다.

여기서 말하는 자동으로 관리해주는 것은 화면에 보이는 1) item View가 스크롤을 하여 화면에서 보이지 않게 될경우, 메모리를 차지할 필요가 없고, 2) 스크롤을 하여 보이는 item View는 새로 만들어서 메모리를 차지할 필요가 없기 때문에 2 번에서 필요한 item View를 1 번의 것을 재사용 하여 메모리를 관리해주는 줄 알았습니다.

그런데 이번에 블로그를 읽으면서 알게 된 것은 adapter의 override 메소드 getView( int position, View convertView, ViewGroup parent) 이 메소드의 convertView를 이용하지 않으면 위에서 말한 재사용은 따로 되지 않는 것으로 이해를 하였습니다. (제가 토이 프로젝트로 한 것에는 convertView를 전혀 이용하지 않았네요...) -------> 일단 이 점이 맞는지 모르겠네요

이제 ViewHolder 라는 것으로 들어오면, 1 ViewHolder는 adapter나 ListView의 안에 정의되어 있는 내부 클래스나 인터페이스는 아니고, ListView의 최적화(성능 향상)을 위해 개발자가 따로 정의해야 하는 것이 맞나요?

2 만약 1. 이 맞다면 ViewHolder 클래스를 왜 static으로 선언을 해야하는지 원리? 구조?가 이해되지 않네요...

3 get, set Tag에 대해서 설명 부탁드립니다...(이건 지금 구글링을 통해 알아보는 중이니 바쁘시면 넘어가주셔도 됩니다!)

4 혹시 ListView에 관련해서 다른 중요한 키워드들이 있다면 알려주시면 감사하겠습니다!

밑의 블로그들은 제가 참고한 블로그들 입니다!

http://bellgori.tistory.com/entry/Android-pattern-01-ViewHolder-pattern

http://www.kmshack.kr/2013/09/android-%EC%9C%A0%EC%97%B0%EC%84%B1-%EC%9E%88%EB%8A%94-viewholder-pattern/

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/


조회수 1207


1 답변


좋아요
1
싫어요
채택취소하기

1 . 이해한것이 맞습니다. 리스트뷰를 그리기 위해 adapter를 이용하는데 adapter 의 getView에서 파라미터로 넘어오는 converView 사용하지 않고 매번 새로운 뷰를 inflate하면 메모리 낭비를 하게 됩니다. 그래서 보통 아래처럼 getView가 불릴때 넘어오는 convertView를 사용합니다. getView에서 넘어오는 convertView는 이전에 그려졌던 view를 넘기는데요. 한번도 inflate되지 않은 view라면 null로 전달되는 경우가 있으니 반드시 null체크는 해야합니다.

public View getView(int position, View convertView, ViewGroup parent)
{
    View customView = convertView;

    if(customView == null)
    {
        LayoutInflater inflater=getLayoutInflater();
        customView  = inflater.inflate(R.layout.noteslist_item, parent, false);
    }
    ...

2 . Viewholder클래스를 static으로 하는 이유는 이건 안드로이드의 개념보다는 자바개념을 확실히 알면 이해하실수 있는건데요. ViewHolder 클래스에 static을 붙히지 않아도 돌아는 갑니다. ViewHolder클래스는 보통 클래스안의 클래스로 정의합니다. 이런 클래스를 Nested Class라고 합니다. Nested Class를 사용하는 이유는 코드를 간단하게 표기하고 소스의 가독성과 유지보수를 높히고 싶을때 사용합니다. nested class에서 상위의 클래스의 메소드나 변수를 사용하기도 하는데요. static을 붙히면 컴파일러단에서 에러가 납니다. No enclosing instance of type에러가 나요. nested class에 static을 붙히면 static nested class라고 칭합니다. static nested class는 한곳에서만 사용하는 클래스를 논리적으로 묶어서 처리할 필요가 있을때 사용합니다.
결국 ViewHolder클래스에 static을 붙히는 이유는 상위클래스의 멤버변수나 객체를 사용하지 않겠라는 것 을 명시적으로 표시하는겁니다.

3 . setTag, getTag()함수는 View에 object를 넣고 가져올 수 있게 해주는 메소드입니다. 아래 간단한 code를 예로 설명을 드릴게요. button1, button2뷰에 clickListener를 붙힌다고 가정했을때….

button1.setOnClickListener(new OnClickListener ... );

button2.setOnClickListener(new OnClickListener ... );
 ...

위와같이 각 버튼마다 setOnClickListener붙힐거에요. setOnClickListener안의 onClick 메소드에 각 뷰에 대한 액션을 호출할겁니다.

public void onClick(View v) {
    doAction(1); // 버튼 1일땐 1을 넣고 버튼 2일때 2를 넘기고 싶을때...
}

button2리스너안에 onClick에는 doAction(2);를 호출하겠죠. 하지만 위와같은 방법은 doAction이라는 메소드를 호출하는건 동일하고 파라메터값만 다르다는 이유로 매 리스너마다 위와같은 코드를 넣는것은 매우 비효율적으로 보여집니다. 이럴때 setTag를 이용하면 코드를 더 간결하게 줄일 수 있어요.

button1.setTag(1);
button2.setTag(2);

이제 모든버튼에 동일한 OnClickListener를 사용할 수 있어요.

listener = new OnClickListener() {
    @Override
    public void onClick(View v) {
        doAction(v.getTag());
    }
};

이런식으로 각각의 뷰안에 어떤 값을 저장하고 싶을때 setTag를하고 getTag를 이용해서 값을 읽어올때 사용합니다.

4 . 오래 되긴 했지만 google io의 listview관련 세미나를 보셨는지요? 안보셨다면 한번 훑어보시는것도 좋을거에요. (하지만 영어라는건 함정...)

android-world-of-listview-android

world-of-listview-android-동영상

p.s 혹시 틀린답변이거나 설명이 부족한 답변이라면 누구든지 편집요청 날려주세요~

  • 2016년 03월 08일에 작성됨
    안드로이드, 루비온레일즈

  • 완전 자세한 설명 감사합니다!!! 이거 작성하는데도 오래걸리셨을텐데 정말 감사합니다 ㅠ    TuTanKhamen   2016.3.8 10:01     

로그인이 필요한 기능입니다.

Hashcode는 개발자들을 위한 무료 QnA사이트 입니다. 작성한 답변에 다른 개발자들이 댓글을 작성하거나 좋아요/싫어요를 할 수 있기 때문에 계정을 필요로 합니다.
► 로그인
► 계정만들기
Close