일단, RecyclerView를 보면서 느낀점은 왜 이렇게 복잡하게 해놨지? 였다.
WPF에서는 금방, 그리고 간단하게 구성될 List 와 데이터 연동이 안드로이드에선 몇단계의 세팅을 걸쳐서 이루어진다.
왜 이렇게 불편하게 해놓은건지 모르겠다. 몇번을 해야 기억이 쏙 들러올련지 원....
일단 기본적으로 간단하게 string 데이터를 표시하는 예제를 구현했다.
1. 필요 구성 요소들
- RecyclerView 를 레이아웃에 추가 해야함
- RecyclerView.Adapter를 상속받는 adapter 클래스를 추가해야함
- 해당 클래스 내부에 RecyclerView.ViewHolder 를 상속받는 클래스를 가져야 함
- Activity 든 fragment든 RecyclerView를 사용하는 곳에서 여러 세팅을 해줘야 함.
- RecyclerView의 각 아이템을 보여줄 layout을 생성해야함 (List 의 한 라인을 담당할 레이아웃)
그럼 하나씩 살펴보면
2. RecyclerView를 layout에 추가
- 간단히 layout에 RecyclerView를 선택 - 드래그 드랍으로 배치한다.
3. Adapt 클래스 및 하위 Holder 클래스 생성
- Adapt 클래스는 RecyclerView.Adapt 클래스를 상속 받아야 한다.
- 상속 받을때, ViewHolder 클래스를 자료형으로 넣어줘야 한다.
- 생성 인자값으로 View와 연결할 데이터를 받아야 한다. (예 : Array<String>)
- onCreateViewHolder, onBindViewHolder, getItemCount 함수를 오버라이드 해야한다.
- Adapt 클래스 내부에 ViewHolder를 상속받는 내부 클래스 생성 해야한다
- 해당 클래스는 View를 생성자에서 받아야 한다.
- 아래에서 기술할, RecyclerView 의 각 Row 항목의 layout 의 view 항목들에 실제 데이터를 입력할 수 있도록 코딩해야한다.
public class adapter(val dataSet : Array<String>) : Adapter<adapter.holder>() {
public class holder(itemView: View) : RecyclerView.ViewHolder(itemView)
{
val textView : TextView
init {
textView = itemView.findViewById(R.id.textView)
textView.setOnClickListener {
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): holder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.recycleviewitem,parent,false)
return holder(view)
}
override fun onBindViewHolder(holder: holder, position: Int) {
holder.textView.text = dataSet[position]
}
override fun getItemCount(): Int {
return dataSet.size
}
}
4. RecyclerView의 각 Row 에 해당하는 layout 생성
- 안드로이드 스튜디오 -> project -> 마우스 우클릭 -> new -> Android Resource File -> layout 선택 후 새로 생성
- 필요에 맞게 view 를 이용해서 화면구성. ( id값 필수)
- 최상위 태그에 android:layout_height는 꼭 wrap_content로 설정한다.
5. Activity 혹은 fragment에서 RecyclerView 세팅
- RecyclerView의 layoutmanager 설정
- LayoutManager는 LinearLayoutManager, GridLayoutManager, StaggeredGridLayoutManager 3개가 있다.
- Adapter 연결
- 연결할 데이터 전달
//샘플 데이터 생성
var tempItem = ArrayList<String>()
for (i : Int in 0..100)
{
tempItem.add(i.toString())
}
var adapt : adapter = adapter(tempItem.toArray(arrayOfNulls<String>(tempItem.size)) )
var review : RecyclerView = view.findViewById(R.id.recycleView)
//가로형으로 설정시 코드
//review.layoutManager = LinearLayoutManager(container?.context, RecyclerView.HORIZONTAL, false)
//세로형. 샘플코드는 fragment에서 추가한거라 context 를 가져오는 코드가 다르다.
review.layoutManager = LinearLayoutManager(container?.context)
review.adapter = adapt
그럼, 리사이클 뷰의 데이터가 변경되었을때 UI에 반영하는 방법이 필요할 것이다.
6. 데이터 갱신 to RecycleView
- adapter의 notifyDataSetChanged() 를 이용하여, 데이터의 추가/삭제/수정 등의 항목 변경이 있음을 알린다.
7. 데이터 갱신시 이벤트 받기
- adapter의 registerAdapterDataObserver 를 통해 데이터가 변경되었을때 이벤트 핸들러를 등록할 수 있다.
- java에서는 간단히 추가하는법을 알고 있는데 코틀린에선 어떻게 하는지 모르겠다. 그래서 좀 복잡한 방식으로 풀었다.
- 일단, RecyclerView.AdapterDataObserver 클래스를 상속받는 클래스를 생성한다
- Activity 혹은 fragment 클래스에서 위에 적은 클래스형 변수를 생성한다
- adapter.registerAdapterDataObserver 의 인자값으로 해당 변수를 추가한다.
//클래스 생성 및 onChanged 함수 오버라이드
class AdaptUpdate : RecyclerView.AdapterDataObserver()
{
override fun onChanged() {
super.onChanged()
Log.d("test","onchanged")
}
}
...
//위에서 작성한 클래스형 변수 생성
private lateinit var adaptupdate : AdaptUpdate
adaptupdate = AdaptUpdate()
...
//adapter에 위에서 생성한 변수를 인자값으로 전달
adapt.registerAdapterDataObserver(adaptupdate)
이렇게 할 경우, 데이터가 변경되면 위에 작성한 클래스의 onChanged가 호출된다
'Android' 카테고리의 다른 글
| 상단 Navigation의 옵션메뉴 추가 (0) | 2022.06.13 |
|---|---|
| 상단 Navigation 의 Up사용하기 (뒤로가기) (0) | 2022.06.13 |
| Interface를 통한 Activity-Fragment간 통신 (0) | 2022.06.08 |
| Fragment 및 Activity (Intent) 기초 (0) | 2022.06.08 |
| 사용자 정의 이벤트 발생 및 수신 - otto (Broadcast) (0) | 2022.06.07 |