본문 바로가기
SW Programming/Android

리사이클러 뷰 RecyclerView 정리

by Crystal.k 2017. 4. 26.



RecyclerView  

안드로이드 5.0(롤리팝)에서 발표

RecyclerView 위젯은 ListView의 더욱 향상되고 유연해진 버전입니다. 사용자 작업 또는 네트워크 이벤트에 따라 런타임에 요소가 변경되는 데이터 컬렉션이 있는 경우 RecyclerView 위젯을 사용하세요.

리사이클러 뷰는 리스트 뷰에 비해 상당히 기능적 커스터마이징에 중점을 두고 있습니다. 리스트 뷰에 비해 조금 어려울 수 있지만, 사용자에게 앱에 대한 연결성을 유지시켜주는 머터리얼 디자인에 대한 요구를 충족시키는 복잡한 그리드나 리스트에 아주 유용하게 쓰일 수 있겠죠.


[주요 클래스]

  1. Adapter – 기존의 ListView에서 사용하는 Adapter와 같은 개념으로 데이터와 아이템에 대한 View생성
  2. ViewHolder – 재활용 View에 대한 모든 서브 뷰를 보유
  3. LayoutManager – 아이템의 항목을 배치
  4. ItemDecoration – 아이템 항목에서 서브뷰에 대한 처리
  5. 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는 새롭게 생성될 때만 불립니다.


ViewHolder

리스트뷰에서는 뷰홀더 패턴을 권장했습니다. UI 를 수정할 때 마다 부르는 findViewById( ) 를 뷰홀더 패턴을 이용해 한번만 함으로서 리스트 뷰의 지연을 초래하는 무거운 연산을 줄여주었습니다. 이 문제를 리사이클러 뷰에서는 뷰 홀더 패턴을 항상 사용하도록 함으로서 해결했습니다. 실제로 당신의 앱의 퍼포먼스를 향상시켜주지만 최신의 디바이스는 뷰 홀더 패턴을 사용하지 않은 리스트 뷰나 리사이클러 뷰의 성능 차이는 미세합니다. 단지 차이점은 리사이클링뷰는 뷰홀더 패턴이 강제되는 것일 뿐입니다. 이전의 리스트 뷰는 선택적이었지만 성능 차이가 너무 컸기 때문에 변화된 것으로 생각됩니다.

간과하기 쉬운 중요한 점은 뷰홀더 패턴을 사용한 리스트뷰와 리사이클러뷰의 성능은 같습니다.



LayoutManager

 리스트 뷰는 수직 스크롤만 가능합니다. 리스트뷰를 수평으로 사용할 수는 없었죠. 그러나 이제 리사이클러뷰에서는 수평 스크롤 또한 지원합니다. 뿐만 아니라 더 다양한 타입의 리스트들을 지원하고, 커스텀 할 수 있도록 해줍니다. 많은 타입의 리스트를 사용하기 위해선 RecyclerView.LayoutManager 클래스를 사용하면 됩니다.


-  LinearLayoutManager :  레이아웃으로 수평, 수직 스크롤( 항목을 가로 또는 세로 스크롤 목록으로 표시합니다.)

-  StaggeredGridLayouManager :뷰마다 크기가 다른 레이아웃. 마치 Pinterest 처럼요.( 지그재그형의 그리드 형식으로 항목을 표시합니다.)

-  GridLayoutManager : 격자형 리스트를 만들 수 있습니다. ex.사진첩( 그리드 형식으로 항목을 표시합니다.)


사용자지정 레이아웃 관리자를 생성하려면 RecyclerView.LayoutManager 클래스를 확장하세요.


레이아웃 관리자는 항목 뷰를 RecyclerView 내에 배치하고 사용자에게 더 이상 보이지 않는 항목 뷰를 언제 재사용할지 결정합니다. 뷰를 재사용 (또는 재활용)하기 위해, 레이아웃 관리자는 어댑터에게 뷰의 콘텐츠를 데이터 집합의 다른 요소로 교체하도록 요청할 수 있습니다. 이런 방식으로 뷰를 재활용하면 불필요한 뷰 생성이나 리소스를 많이 소모하는 findViewById() 조회를 수행하지 않아도 되므로 성능이 개선됩니다.


사용 예시

mActivity = getActivity();

mRecyclerView = (RecyclerView) mActivity.findViewById(R.id.recycler_view);

mLinearLayoutManager = new LinearLayoutManager(mActivity.getApplicationContext());

mRecyclerView.setLayoutManager(mLinearLayoutManager);


Item Decoration

리스트 뷰에서는 아래의 파라미터를 XML에 추가함으로서 쉽게 divide할 수 있었습니다. 

리사이클러 뷰에서는 RecyclerView.ItemDecoration 클래스를 통해 divider를 원하는 아이템에 추가해주게 되었습니다. 조금 복잡해졌지만 동적인 데코레이팅이 가능해졌습니다.


Item Animator을 이용해 멋진 앱을 만드세요

 Metarial Design에 대해 조명된 이후로 리스트에서의 애니메이션은 무궁무진한 가능성을 가지게 되었습니다. 리스트 뷰에서는 아이템의 삽입이나 삭제에 특별한 애니메이션이 없었습니다. 하지만 리사이클러 뷰에서는 RecyclerView.ItemAnimator 클래스를 통해 애니메이션을 핸들링 할 수 있게되었죠. 이 클래스를 통해서 아이템 삽입, 삭제, 이동에 대한 커스터마이징이 가능하고, 또한 DefaultItemAnimator가 제공되므로 커스터마이즈가 필요 없이 사용할 수도 있습니다. notifyItemChanged(int position), notifyItemInserted(int position), notifyItemRemoved(int position)을 ItemAnimator을 통해 특정 아이템에 대한 애니메이션을 발생시킬 수 있습니다.


클릭 이벤트 처리

  • 터치 이벤트를 통해 사용자가 아이템을 클릭 했는지 롱클릭 했는지를 직접 처리 

RecyclerView.OnItemTouchListener은 리사이클러 뷰의 터치 이벤트를 감지합니다. 좀 복잡하지만 개발자에게 터치 이벤트를 인터셉트하는 제어권한을 주게되었죠. 안드로이드 공식 문서에서는 터치 이벤트를 인터셉트함으로서 리사이클러 뷰에게 전달하기 전에 조작함으로서 유용하게 사용될 수 있다고 합니다. (ListView에서 아이템을 클릭시 콜백 받을수 있는 리스너는 RecyclerView에서는 존재하지 않음) 

문제점:실제로 사용시 문제 점이 발견되어 쉽게 처리가 불가능할것 같다. 이유는 스크롤시 사용자가 스크롤을 멈추기 위해 화면을 터치 하는 순간 onSingleTapConfirmed 이벤트가 발생하는 문제점이다. 이렇게 되면 사용자는 스크롤을 멈추는게 아닌 아이템클릭으로 인식 되는 오작동이 생기기 때문에 이런 문제를 해결하기위해 좀 더 추가적인 작업이 필요하다.

 

  •  ViewHolder에서 OnClickListener를 직접 달아주어 처리해야합니다. (나는 이걸로함)

public class ViewHolder extends BaseViewHolder<Post> {

private ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 클릭이벤트설정


}
});
}


  • RecyclerItemClickListener 를 만들어서 addOnItemTouchListener 를 이용해서 RecyclerView 에 붙인다. http://stackoverflow.com/questions/24471109/recyclerview-onclick/26196831#26196831

recycler view 안에 button 등이 있는 경우에 문제가 발생, recyclerview 안의 버튼을 누르면, recyclerview 에도 event 가 발생하고, recyclerview 안에 있는 button 에도 event 가 발생해 버렸다고 한다





RecyclerView 새로고침


notifyDataSetChanged : 데이터가 전체 바뀌었을 때 호출. 즉, 처음 부터 끝까지 전부 바뀌었을 경우

notifyItemChanged : 특정 Position의 위치만 바뀌었을 경우. position 4 번 위치만 데이터가 바뀌었을 경우 사용 하면 된다.

notifyItemRangeChanged : 특정 영역을 데이터가 바뀌었을 경우. position 3~10번까지의 데이터만 바뀌었을 경우 사용 하면 된다.

notifyItemInserted : 특정 Position에 데이터 하나를 추가 하였을 경우. position 3번과 4번 사이에 넣고자 할경우 4를 넣으면 되겠죠

notifyItemRangeInserted : 특정 영역에 데이터를 추가할 경우. position 3~10번 자리에 7개의 새로운 데이터를 넣을 경우

notifyItemRemoved : 특정 Position에 데이터를 하나 제거할 경우.

notifyItemRangeRemoved : 특정 영역의 데이터를 제거할 경우

notifyItemMoved : 특정 위치를 교환할 경우 (Drag and drop에 쓰이겠네요^^)




리스트 보여줄 때 데이터의 전부를 가져오지 않고, 일정 갯수만큼씩 추가해서 업데이트 해주기

http://isntyet.tistory.com/114


리스트뷰 스크롤뷰 등등 당겨서 새로고침하기

https://github.com/chrisbanes/ActionBar-PullToRefresh


반응형

댓글