5.0(롤리팝) 버전이 ListView 보다 유연하고 성능이 향상된 RecyclerView와 함께 발표되었다. 기존의 ListView는 커스터마이징 하기에 힘들었고, 구조적인 문제로 성능상의 문제도 있었다. RecylerView는 ListView의 문제를 해결하기 위해 개발자에게 더 다양한 형태로 커스터마이징 할 수 있도록 제공되었다. RecyclerView와 ListView의 가장 큰 차이점은 Layout Manager와, View Holder 패턴의 의무사용, Item에 대한 뷰의 변형이나 애니메이션할 수 있는 개념이 추가 되었다. 리스트 뷰의 성능 상의 이슈도 해결해주면서, 많은 타입의 뷰들을 가독성 있게 보여줄 수 있는 뷰가 리사이클뷰이다.
주요 클래스
- Adapter - 기존의 ListView에서 사용하는 Adapter와 같은 개념으로 데이터와 아이템에 대한 View생성.
- ViewHolder - 재활용 View에 대한 모든 서브 뷰를 보유.
- LayoutManager - 아이템의 항목을 배치
- ItemDecoration - 아이템 항목에서 서브뷰에 대한 처리
- ItemAnimation - 아이템 항목이 추가, 제거되거나 정렬될 때 애니메이션 처리
Adapter
리스트 뷰는 데이터가 어디서 왔냐에 따라 BaseAdapter를 상속한 ArrayAdapter(배열로부터 데이터를 가져올 경우), CursorAdapter(DB로 부터 가져올 경우), sIMPLEaDAPTER(xml 등으로 부터 가져올 때)를 구분하여 사용합니다. 하지만 리사이클러 뷰는 Universal한 Adapter를 사용하여 데이터 소스를 처리합니다. 이것은 리사이클러 뷰의 유연성을 보여줍니다. 다음의 3가지 인터페이스를 구현해야 합니다.
- onCreateViewHolder(ViewGroup parent,int viewType) : 뷰 홀더를 생성하고 뷰를 붙여주는 부분
- onBindViewHolder(ListItemViewHolder holder,int position) : 재활용 되는 뷰가 호출하여 실행되는 메소드, 뷰 홀더를 전달하고 어댑터는 position의 데이터를 결합시킵니다.
- getItemCount() : 데이터의 개수를 반환
리스트 뷰가 사용했던 getView() 메소드는 매번 호출되면서 null 처리를 해줘야했다면, onCreateViewHolder는 새롭게 생성될 때만 호출된다.
리스트뷰에서는 뷰홀더 패턴을 권장했었는데, UI를 수정할 때 마다 부르는 findViewById() 를 뷰홀더 패턴을 이용해 한번만 함으로서 리스트 뷰의 지연을 초래하는 무거운 연산을 줄여주었다. 이 문제를 리사이클러 뷰에서는 뷰 홀더 패턴을 꼭 사용하도록 함으로써 해결했다.
뷰홀더 패턴은 오래된 기기일수록 효과가 좋지만, 최신기기같은 경우 사용 유무에 대한 성능차이는 미미하다. 뷰홀더 패턴을 사용한 리스트뷰와 리사이클러뷰의 성능은 같다. 단지 차이점은 리사이클링뷰는 뷰홀더 패턴이 강제된다는 차이점이 있다.
LayoutManager
리스트뷰는 수직 스크롤만 가능하다. 리스트뷰를 수평으로 사용할 수 없었는데, 리사이클러뷰에서는 수평 스크롤을 지원해줍니다. 뿐만 아니라 더 다양한 타입의 리스트들을 지원하고, 커스텀할 수 있도록 해준다. 리사이클러뷰는 아래와 같은 3가지의 미리 정의된 Layout Managers를 제공한다.
- LinearLayoutManager : 리사이클러 뷰에서 가장 많이 쓰이는 레이아웃으로 수평,수직 스크롤을 제공하는 리스트를 만들 수 있다.
- StaggeredGridLayoutManager : 뷰마다 크기가 다른 레이아웃을 만들 수 있다.
- GridLayoutManager : 사진첩 같은 격자형 리스트를 만들 수 있다
리사이클러뷰에서는 RecyclerView.ItemDecoration 클래스를 통해 divider를 원하는 아이템에 추가해줄 수 있다. 조금 복잡해졌지만 동적인 데코레이팅이 가능해졌다
Item Animator
리사이클러 뷰에서는 RecyclerView.ItemAnimator 클래스를 통해 애니메이션을 핸들링 할 수 있게 되었다. 이 클래스를 통해서 아이템 삽입,삭제,이동에 대한 커스터마이징이 가능하고, 또한 DefaultItemAnimator가 제공되므로 커스터마이즈가 필요 없이 사용할 수도 있다. notifyItemChanged(int position), notifyItemInserted(int position), notifyItemRemoved(int position)을 ItemAnimator을 통해 특정 아이템에 대한 애니메이션을 발생시킬 수 있다.