Android #8 - RecyclerView (국비34일차)

 

 

1. ViewHolder
2. RecyclerView
3. 예제 (애니 원피스)

 

 

ListView는 속도 측면에서

문제가 있었다.
(아이템이 많을수록 버벅거리는...)

이 문제는 우리가 기본적으로 사용하던

findViewById에서 발생했는데

이 작업이 시간이 오래걸리는 알고리즘으로 되어있기 때문이었다.

 

한 개발자가 이를 발견하고 

뷰들을 객체로 관리하는 방식을 고안해 냈다.
(이 방식이 viewHolder)

 

그리고 이 방식이 점차 대중화되자

안드로이드 팀에서 기존 listview와 gridview를

개선한 RecyclerView를 만들었다.

 

 

개선한 뷰를 공부하기 전에

ViewHolder를 먼저 공부해 보자.

 

 

 

 

1. ViewHolder

 

어제 마지막에 했던 심화예제를

비슷하지만 간단한 형식으로 만들어보자.(ViewHolder 공부를 위해)

2023.02.16 - [Android journey/Android] - Android #7 - AdapterView (국비 33일 차)

 

Android #7 - AdapterView (국비33일차)

오늘은 안드로이드에서 가장 많이 사용한다는 AdapterView에 대해서 공부할 것이다. 오늘은 이 뷰가 어떻게 작동하는지에 대해서 알아보고 이 원리를 이용해 제일 많이 사용하는 View(AdapterView를 상

d0ngurrrrrrr.tistory.com

우선 메인액티비로 와서

대량의 데이터를 담을 ArrayList를 만들어주자.

 

그리고 activity_main으로 와서

리스트뷰를 만들어주고

 

 

내가 원하는 화면을 커스텀하기 위해

listview_item이라는 레이아웃 파일을 만들어주자.

(만든 모습)

여기서 내가 원하는 레이아웃을

짜주면 되겠다.

 

이제 어답터를 만들어야 한다.

자바 클래스를 만들어

어답터 클래스를 만들어주고

 

 

기본적인 참조변수와

생성자까지 적어주자.

그리고 BaseAdapter를 상속받았으니

그 안에 있던 기능들을 구현해 주자.

 

그리고 getView 같은 기능들을 사용하기 전에

ViewHolder라는 클래스를 MyAdapter class안에

이너클래스로 만들자.

 

이때 이 클래스 안에는

내가 커스텀한 뷰들의 참조변수가 들어가야 하고

생성자를 만들어서

참조변수 안에 findViewById를 이용해

값을 넣어줘야 한다.

 

 

 

 

getView에는

어제 한 거와 같이

layoutInflater를 만들어서 inflate 시킨다.

 

하지만 여기선 뷰홀더를 이용해

각 뷰의 Tag값 안에 홀더를 넣어주고

Tag 값 안에 저장되어 있던 값을 이용해

아이템을 bind해준 형태다.

 

 

그리고 메인 자바 파일로 

와서 리스트뷰에 

setAdapter를 해주면 끝.

 

 

이 방식은 기존 방식과 다르게 속도가

빠른 장점을 가지고 있다. 

 

그래서 안드로이드 팀은

이 기능을 이용한

RecyclerView를 만들어서

발표를 한다.

 

 

 

 

2. RecyclerView

 

 

 

우선 activity_main.xml에서

RecyclerView를 만들어주자.

 

RecyclerView를 사용할 때

레이아웃 형태를 정해줘야 한다.

layoutmanager라는 속성을 통해 어떤 레이아웃을

사용할지 설정해야 한다.
(id도 꼭 주자..)

 

Gridelayout은 격자 형태

Linearlayout은 일자 형태

StraggeredGridLayout은 불규칙 격자 형태를 말한다.

 

LinearLayout 형태로 설정하면 

방향 설정을 필수다.

 

그리고 이제 뷰에 들어갈 아이템들을

설정할

클래스를 만들어주자.

그리고 내가 필요한 아이템들의 참조변수를 선언해 주자.

그 후 생성자를 만들어줘야 한다.

하나하나 작성하기 귀찮을 땐

alt + insert 키를 누르면 위의 화면 같이 나오는데

Constructor를 눌러서

내가 선언한 참조변수들을 선택하고

ok를 눌러주자.

그럼 위와 같이 

생성자가

자동으로 만들어진다.

 

 

이제 메인 자바 파일로 돌아가서

어레이 리스트를 만들고

대량의 데이터를 추가해 주자.

 

그리고 새로운 레이아웃 xml 파일을 만들어주자.
(내가 생각한 대로 레이아웃을 커스텀하기 위해)

이때 root element는 cardview로 써보자.

 

카드뷰에서 padding 값을 줄 땐

contentpadding으로 줘야 하며

 

cardElevation은 

내가 만든 카드 아래에 나오는 그림자 같은 것이다.

선택된 카드 영역 아래에

음영이 보이는가?

저 부분이다.

 

그리고 cornerRadius를 줘서

카드를 덜 각지게 만들어주었다.

 

 

여기서 알아둬야 할 점이

카드뷰는 frameView를 상속받은 것이라서

그 안에 뷰를 만들면

겹쳐 보인다.
(그래서 Relative, linearLayout을 안에 사용함)

 

그래서 RelativeLayout을 만들고

 그 안에 커스텀할 뷰들을 만들어주었다.

 

그러면 미리 보기 화면이 이렇게 나올 것이다.

 

이제 내가 커스텀한 레이아웃을

적용시키기 위해

나만의 어뎁터를 만들어야 한다.

새로운 자바 클래스를 만들자.

나의 어댑터를 만들 때

RecyclerView.Adapter를 상속받아야 한다.
(BaseAdapter는 RecyclerView에 쓸 수 없음)

그럼 빨간 줄이 뜨는데 커서를 올려서

추상 메서드를 만들어주자.

기존 BaseAdapter를 상속받았을 때완 달리

3개의 메소드가 나타난다.
(필요 없는 메소드를 없애버린 것..)

 

여하튼

상속을 받아주고

context와 배열 참조변수를 만들고

생성자도 만들어준다.

그 후 MyAdapter 클래스 안에

이너클래스인 VH를 만들고

RecyclerView.ViewHolder를 상속받아주고

내가 커스텀한 화면에 들어갈

뷰들을 만들어준다.

그리고 생성자 함수를 만들어준다.
(뷰홀더는 저 뷰들을 관리하게 만들어진 클래스니까..)

 

이제 onCreateViewHolder로 와서

우리가 어제 계속했던

inflater를 만들어서 inflater를 해준다.

그리고 뷰 홀더객체를 만들어서

그 홀더를 return 해준다.

 

 

그리고 onBindViewHolder 메소드로 가서

현재번째 아이템요소를 얻어와서

뷰에 넣어줘야 한다.

이를 위해 

Vh를 통해서

item의 현재 몇 번째인지 position을 통해 받아서

각각의 뷰들에 넣어주었다.

 

 

 

이제 막바지 작업이다.

메인액티비티 자바로 와서

RecyclerView와 Adapter를 참조변수로 만들어서

 

setAdapter를 해주면 된다.

 

그럼 위와 같은 결과물이 나온다.

이제 저 아이템들을 눌렀을 때

반응하게 하려면 리스너 처리를 해야 한다.

하지만 리사이클러뷰엔 그 기능이 없다.

그래서 어뎁터에 가서 만들어줘야 한다.

 

이 onClickListener를 만들려면

itemView가 선언된 곳에 해야 하는데

그럼 onCreateViewHolder에 할 수 있지만

여기다 하면 코드가 더러워져서

여기를 선호하지 않는 개발자도 많다고 한다.

 

그래서 다른 개발자들이 찾아낸 방식은

VH(뷰 홀더) 클래스로 가서

리스너 처리를 하는 방식이다.

이 방식으로 

커스텀한 아이템을 가져올 수도 있다.

 

 

 

 

3. 예제 (애니 원피스)

완성화면

 

우선 액티비티 메인 xml에서

RecylcerView를 만들어준다.

 

그리고 대량의 데이터를 넣기 위해

내가 원하는 자료형들이 있는

클래스를 만든다.

이때 생성자도 만들자.

 

 

메인 자바 파일로 와서

참조변수들을 만들고

대량의 데이터를 추가해 준다.

 

 

 

그리고 이제 내가 원하는 레이아웃을

만들기 위해서

circle imageview가 필요하다.

 

구글에서 검색을 한 뒤 위의 깃헙에 들어간다.

아래로 스크롤을 내리다 보면

Gradle 부분이 있는데

implementation 부분을 복사해서

내 프로젝트 파일 중

Gradle Scripts 안에

build.gradle에 넣어야 한다.
(module :app)

아래로 내리다 보면

dependencies 부분이 있는데

여기에 붙여 넣기를 하면 된다.

 

그 후 내가 커스텀할 레이아웃을 만들기 위해

레이아웃 파일을 만들어주자.

그리고 내가 추가할

뷰들을 넣어주자.

요런 형식으로 만들었다!

 

 

그럼 이제 어답터를 만들어야 한다.

새로운 자바 파일을 만들어주고

RecyclerView.Adapter를 상속받은 어답터를 만들어주자.

그리고 참조변수도 선언해 주자. (+생성자도)

그런데 처음 보는 게 보인다.

바로

extends 끝부분에 <>!!!

<> 안에 있는 것은 바로 다음으로 만들

뷰홀더 클래스이다.

뷰홀더 클래스를 만들고

안에 넣어주면 된다.

 

 

뷰홀더 클래스를 만들면서

RecyclerView.ViewHolder를 상속받아줘야 한다.

뷰홀더엔 내가 

커스텀한 뷰들의 참조변수를 선언해야 하고

생성자를 만들어

그 안에 뷰들의 참조변수에 뷰 값을 넣어줘야 한다.

 

그리고 1번에서도 말했지만

클릭 리스너는 여기에 위치하는 것이 좋다.

 

 

onCreateViewHolder는 

뷰가 만들어졌을 때 실행되는 것이다.

여기선 Inflater를 통해 inflater를 하고

뷰홀더를 리턴해준다.

 

그리고 onBindViewHolder부분에서는

그게 몇 번째 아이템 요소인지 

item으로 받아와서

뷰홀더 객체가 가지고 있는 자식뷰들에게

아이템 값을 연결해 주자.

이건 아이템이 몇 개나 생성될 건지

적는 것! (다 알쥬?)

 

 

이제 메인 자바 파일로 와서

setAdapter만 해주면 끝이다.

 

 

여기서 하나 더 들어가자면

add와 delete 버튼을 만들어 누르면

하나가 생성되고 하나가 없어지는 것과

linearlayout과 gridlayout을

원하는 대로 설정하는 버튼을 만들어보자.

 

우선 액티비티 메인 xml에 버튼을 추가해 주고

 

각각 findViewById를 통해 

버튼에 뷰를 넣고

리스너를 만들어주자.

저번에는

아이템이 추가되면

notifyDataSetChanged를 썼는데

이는 전체 뷰를 갱신하는 것이라
( 여러 개가 변경되었을 때 쓰자.)

권장하지 않는다.

대신 notifyItemInserted를 통해 추가를 해주고

 

아이템을 제거했을 땐

remove를 하고

notifyItemRemoved를 해주자.

 

리니어와 그리드 레이아웃으로

바꾸는 버튼은

우선 버튼 참조 변수에 뷰를 받아주고

리스너를 생성한 다음에

레이아웃 매니저를 통해서

설정을 해준 다음

recyclerView한테 setLayoutManaer를 하라고 명령을 내리면 끝이다.

Grid 레이아웃도 방법은 같다.