리스트뷰 레퍼런스



ListView 관련 포스트

[Android] 커스텀 리스트뷰 : Custom ListView - Layout : 레이아웃

[Android] 리스트뷰 아이템 클릭 이벤트 - ListView Item Click

[Android] ListView(리스트뷰) 아이템 추가/삭제




 ListView, [View getView() in Adpater]

ListView는 화면에 보여줄 하나의 아이템에 해당하는 뷰를 ArrayAdapter의 getView 메소드에서 만들어냅니다.

getView에서 View를 생성하고, 데이터를 입혀서 반환하는 거죠. 기본적으로는 아래와 같습니다.




이제 이 getView 메소드를 재구현하는 여러가지 방법들을 알아보도록 하겠습니다.


Dumb

위의 방법은 매 position마다 View를 새로 생성합니다.
하나의 View를 새로 생성해 내는건 당연히 엄청난 노력이 필요하겠죠.




Correct

Correct code는 Dumb code에서 조금 개선한 코드입니다.
Adapter에서는 View를 자동적으로 재활용하기 때문에 그걸 이용해서, 이미 뷰를 생성해 놓은 상황이라면 새로 생성하지는 않고, 그 뷰를 통해 자식 뷰들을 찾아와 데이터를 바꿔서 리턴하는 것입니다.

하지만 여기서도 약간의 속도저하의 원인이 남아있는데요, 그건 바로 findViewById()라는 메소드 입니다.

어떤 뷰에서 입력한 id에 해당하는 View를 리턴해 주는 메소드인데요, 이 메소드는 layout에서 계층구조가 심해질수록 더 오래걸리겠죠.
그래서 findViewById 메소드까지 최소한으로 사용하도록 개선하면 더 좋습니다.




Fast
 



이 세가지 방법에 대해 성능을 측정한 결과라고 합니다.
10,000개의 데이터를 가진 List를 통해 ListView 및 Adapter를 만들고,
위의 세가지 방법으로 getView를 만들어서 측정을 한것이죠.




Posted by croute

댓글을 달아 주세요

  1. Favicon of http://blog.naver.com/sungkyu89 BlogIcon 홍성규 2011.12.31 13:32  댓글주소  수정/삭제  댓글쓰기

    안녕하세요^^ 좋은 내용 감사합니다.

    제가 주소록을 불러와서 리스트뷰에 출력하려고하는데, 주소록 데이터가 100개 이상이다보니
    성능적인 문제가 걱정이 되더라구요-_ㅠ 그래서 포스팅해주신 내용으로 성능을 개선시켜보려했으나;
    실패하였습니다ㅠ

    이유인 즉슨 제 커스텀 리스트뷰 레이아웃에는 체크박스가 있는데요.. 생성되었던 기존의 뷰를 재사용하다보니 이 체크박스가 문제를 일으켰습니다.. 예를 들자면 1번 아이템의 체크박스를 체크하면 1번 아이템 뷰를 재사용한 11번 아이템의 체크박스까지 같이 체킹이 되는겁니다.. 음.. 저도 계속 연구를 해볼테지만 혹시 좋은 해결책이 있으시다면 한 수 부탁드리겠습니다^^;

    어느새 2011년 마지막날이네요. 좋은 연말/연초 보내시기 바랍니다^^

    • Favicon of https://croute.me BlogIcon croute 2012.01.01 02:28 신고  댓글주소  수정/삭제

      당연히 해결책이 있지요 ㅋ
      저도 리스트뷰를 처음쓸때 많이 겪었던 문제입니다. ㅎㅎ
      일단, 연초이니, 월요일부터 ㅎㅎㅎㅎ

    • Favicon of https://croute.me BlogIcon croute 2012.01.02 10:23 신고  댓글주소  수정/삭제

      보통 getView에서 뷰에 데이터를 뿌려주잖아요.
      이때, 데이터에도 CheckBox에 대한 값을 저장할 수 있도록 변수를 하나 만들어 주고,
      check 상태가 변할때 데이터도 변경해 주도록 합니다.
      그리고 getView에서는 데이터로부터 읽어와서 CheckBox의 상태를 세팅해주면 되지요.

      이런일이 발생하는건 아시다시피, 어댑터에서 화면에 보이는 갯수만큼만 뷰를 만들고(getView에서) 그 뷰를 재활용하기 때문인데요, 뷰는 재활용하지만 데이터는 유일하기때문에 CheckBox가 중복되는것을 피할 수 있지요.

  2. Favicon of http://blog.naver.com/sungkyu89 BlogIcon 홍성규 2012.01.02 12:00  댓글주소  수정/삭제  댓글쓰기

    아! 체크박스의 보여주기 위한 그래픽기능과 체크유무를 표현하는 데이터기능을 분리해 놓으면 되는거였네요!
    왜 그 생각을 못했을까요ㅋㅋㅋㅋ getView()가 호출될때마다 체크박스를 생성해서 각 항목마다 독립적인
    체크박스를 집어넣으려고 뻘짓 중이었는데.. 감사합니다!!

    스타플 어플 잘쓰고 있어요ㅋㅋㅋ^^

  3. voodooft 2012.12.27 10:36  댓글주소  수정/삭제  댓글쓰기

    안녕하세요 C라우트님!!
    리스트뷰 최적화와 관련하여 궁금한 사항이 있어서요~

    보통 sns의 경우 글을 쓴 유저의 프로필사진, 닉네임, 글내용, 첨부이미지 정도가 있는데요..
    위와같이 holder를 사용할 경우 리스트뷰 상에서 최초 그려진 뷰를 재사용 하게 되는데
    이렇게 되면 첨부이미지가 있을경우와 없을경우를 데이터 셋팅 부분에서 모두 셋팅 해줘야 하는거
    아닌가요...?
    현재 getView에서 첨부 이미지 관련하여 처리하는 방식은 layout에서는 이미지뷰의
    visible을 gone으로 해두고 글에 첨부 이미지가 있을 경우에만 visible을 visible로
    셋팅하고 이미지를 불러오도록 되어있거든요... 그렇다면 위와 같이 holder를 이용하여 처리할 경우
    이미지가 없을 경우도 visible을 gone으로 처리해주고 이미지를 날려주는 작업을
    해야 하는거 아닌가요...? 그렇다면 이것 또한 그닥 빠르지 않을것 같아서... 잘 모르겠어서요 ㅠ_ㅠ

    그리고 프로필사진의 경우 getView에서 비동기 방식으로 다운로드하여 다운로드완료될 시 셋팅 하도록 하고
    다음에 또 getView가 될시에는 소프트레퍼런스로 임시저장된 이미지 데이터를 불러오도록 되어있는데요~
    이전에 그려진 뷰에 있는 프로필 사진이 다음행에 다른 유저의 프로필 사진으로 보여지며 다른유저의 프로필
    사진이 다운로드 완료될시 이미지가 바뀌는 현상이 있구 해서요... 그리고 이 현상은 첨부이미지가 있는 글이
    연속으로 있을 경우에도 마찬가지구요... 같은 이미지가 두개 연속 뜨고 비동기로 이미지 다운로드가 완료되면 바뀌는...

    위 예제와 같이 간단한 경우엔 holder를 쓰기가 용이한데 제가 쓰기엔 좀 애매한 부분이 있어서요~
    어떻게 처리하면 좋을까요...?

    실은 지금 메모리 문제에 직면해서.... 리스트뷰 최적화를 알아보고 있는데...
    한장의 이미지를 보여주던 곳에 gif를 보여주게 하고있는데....
    이 gifView가 결국엔 gif의 모든 프레임을 bitmap화하여 가지고 있으면서
    delay를 수시로 체크하면서 다음 프레임을 보여줄때가 되면 다음프레임을 셋팅하도록 되어있는데
    이게 프레임 수가 많을수록 엄청난 용량을 차지해서요....

    현재 리스트뷰의 UI는 글이 평소엔 접혀있다가 터치시 늘어나면서 첨부이미지를 보여주는 방식이라
    달리 글상세 페이지가 없거든요... 그래서 접혀있을 땐 썸네일만 보여주고 펼쳤을 때는 gif를 로딩해서 보여주고 접었을시 또는 다른 것을
    펼쳤을 시 기존 뷰에 있는 gif를 free 시켜주도록 구현하고 싶은데요...

    getView와 반대기능을 하는.... 기능이 있다면 화면에서 뷰가 벗어날 때 free를 시켜주고 싶은데 그걸 잘 모르겠네요.... ㅠ_ㅠ

    • voodooft 2012.12.27 11:49  댓글주소  수정/삭제

      우선 gifView는 onDetachedFromWindow()시에 free() 하도록 처리하였습니당 ^^; 하지만 아직도 holder 사용법은 잘 모르겠네요... ㅠ_ㅠ

    • Favicon of https://croute.me BlogIcon croute 2012.12.27 22:24 신고  댓글주소  수정/삭제

      안드로이드 이미지 캐싱 관련해서 구글 레퍼런스를 참고하면 해결할 수 있을 것 같네요.

      도큐먼트
      http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

      예제
      http://developer.android.com/shareables/training/BitmapFun.zip

      예제를 보면, 이미지 다운로더 부분에서 디폴트로 이미지가 없을 경우에 보여질 이미지를 세팅할 수 있거든요.

      gif 라면.. 음.. native 쪽에서 처리를 하는게 훨씬 가벼울것 같기는 한데..
      Frame animation 은 조금 무거운 부분도 있고, out of memory 가 나기도 쉬워서요. 음.. 고민이 필요한 부분이겠네요.