1. ListView
- ListView는 아이템의 전체 개수가 아닌 화면에 보여지는 개수 만큼만 View를 그려놓는다.
- listview는 adapter가 연결되어있어야 본인 데이터들을 직접 input 를 넣어줄 수 있음
<adapter 만들기> -UserAdpaterKt
Adapter는 전원을 연결할 때 쓰임 -> 비슷하게 데이터와 아이템에 대한 뷰를 생성해주는 기능 : 데이터를 관리하고 뷰를 관리하는 기능이다.
class UserAdapter (val context: Context, val UserList: ArrayList<User>) : BaseAdapter()
- UserAdapter.kt 코틀린 파일에서 val 변수 로 선언한다. (*이후 ':' 로 할당받음)
- val UserList: ArrayList<User> : User 라는 모듈을 기준으로 list로 받아온다.
- BaseAdapter를 상속받는다. (':') (extends)
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View{
val view: View = LayoutInflater.from(context).inflate(R.layout.list_item_user)
}
- listview의 한 컬럼당의 아이템은 list_item_user 를 따르게 한 코드 (list_item_user를 붙인 것)
val profile = view.findViewById<ImageView>(R.id.iv_profile)
- findviewId : iv_profile 의 id를 찾게 한다.
아래는 adapter 생성 실습 주요(전체) 코드이다.
class UserAdapter (val context: Context, val UserList: ArrayList<User>) : BaseAdapter()
{
override fun getCount(): Int {
return UserList.size
}
override fun getItem(position: Int): Any {
return UserList[position]
}
override fun getItemId(position: Int): Long {
return 0
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val view: View = LayoutInflater.from(context).inflate(R.layout.list_item_user, null)
val profile = view.findViewById<ImageView>(R.id.iv_profile)
val name = view.findViewById<TextView>(R.id.tv_name)
val age = view.findViewById<TextView>(R.id.tv_age)
val greet = view.findViewById<TextView>(R.id.tv_greet)
val user =UserList[position]
profile.setImageResource(user.profile)
name.text = user.name
age.text = user.age
greet.text = user.greet
return view
}
- 각 function마다 return을 꼭 적어줘야한다.
- getCount 를 통해 리스트 길이를, getItem를 통해 리스트 요소를, getView를 통해 레이아웃을 연결했다.
이후 MainActivity.kt 의 코드다
class MainActivity : AppCompatActivity() {
private lateinit var binding : ActivityMainBinding
var UserList = arrayListOf<User>(
User(R.drawable.android, "홍드로이드","22","안녕하세요"),
User(R.drawable.android, "자바","22","안녕하세요"),
User(R.drawable.android, "자바스크립트","22","안녕하세요"),
User(R.drawable.android, "코틀린","22","안녕하세요"),
User(R.drawable.android, "스위프트","22","안녕하세요"),
User(R.drawable.android, "안드로이드","22","안녕하세요"),
User(R.drawable.android, "리액트 네이티브","22","안녕하세요")
)
override fun onCreate(savedInstanceState: Bundle?) { //액티비티의 실행 시작 시점
super.onCreate(savedInstanceState)
binding= ActivityMainBinding.inflate(layoutInflater) //뷰를 객체화?
setContentView(binding.root)
//val item = arrayOf("사과", "배", "딸기","키위","홍드로이드")
//context란 한 애티비티의 모든 정보를 담고있다.
//binding.listView.adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1,item)
val Adapter = UserAdapter(this, UserList)
binding.listView.adapter = Adapter
}
}
- User 모델을 기반으로 한 arrayListOf를 사용하여 list를 생성한다. (drawable > android 리소스는 리소스도 int형 이기에 가능하다.
- val Adapter = UserAdapter(this, UserList) 를 통해 UserAdapter.kt 으로 context와 userlist 의 매개변수를 보낸다. 이후 adapter를 연결시킨다. (binding.listView.adapter = Adapter)
2. Recycler View
- listview 의 업그레이드 버전 (더 자주 사용되고 있음)
<adapter 만들기> -ProfileAdapterKt
implementation("androidx.recyclerview:recyclerview:1.3.0-rc01")
- recyclerview의 종속항목 선언이다. build.gradle > dependencies 에 추가한다. (1.3.0 버전)
아래부터는 ProfileAdapter.kt 에 대한 설명이다.
class CustomViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val gender = itemView.findViewById<ImageView>(R.id.iv_profile) //성별
val name = itemView.findViewById<TextView>(R.id.tv_name) //이름
val age = itemView.findViewById<TextView>(R.id.tv_age) //나이
val job = itemView.findViewById<TextView>(R.id.tv_job) //직업
}
- ViewHolder란 각 뷰들을 보관하는 holder 객체를 의미한다.
- findViewById 를 이용하여 변수를 저장한다.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProfileAdapter.CustomViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false) //뷰연동: LayoutInflater는 XML에 정의된 Resource를 View 객체로 반환해주는 역할
//context (액티비티의 정보)를 가져와서 layoutinflater에 적용시킨다. 이후 inflate를 통해 list_item.xml를 붙여준다.
return CustomViewHolder(view)
}
- viewholder를 이용해서 list_item.xml 를 연동한다. (LayoutInflater 는 xml에 정의된 리소스를 뷰객체로 반환)
- context (액티비티의 정보)를 가져와서 layoutInflater에 적용시키고 list_item.xml를 붙인다(inflate).
- customViewHolder의 매개변수로 위의 값을 넘겨준다.
override fun onBindViewHolder(holder: ProfileAdapter.CustomViewHolder, position: Int) {
//oncreateviewholder를 실제로 바인딩한다, 스크롤할때, 리스트뷰를 사용할때 onBindViewholder가 지속적으로 호출 view에 대해 안정적으로 데이터들을 매치시켜주는 곳
holder.gender.setImageResource(profileList.get(position).gender)
holder.name.text = profileList.get(position).name //positon은 완성했을 때 위치 (0~), 바인드뷰마다 position 별로 연동시켜줌
holder.age.text = profileList.get(position).age.toString() //나이는 int라 settext바로 못함, toString으로 문자열 형태로 변환해야함.
holder.job.text = profileList.get(position).job
}
- onBindViewHolder로 실제로 바인딩을 시킨다. 스크롤할때, 리스트뷰를 사용할 때 등 지속적으로 호출되는 함수이다.
- 바인드 뷰마다 position 별로 연동시켜준다.
이후 ProfileAdapter.kt 의 코드이다.
class ProfileAdapter (val profileList: ArrayList<profiles>) : RecyclerView.Adapter<ProfileAdapter.CustomViewHolder>()
{
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProfileAdapter.CustomViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false) //뷰연동: LayoutInflater는 XML에 정의된 Resource를 View 객체로 반환해주는 역할
//context (액티비티의 정보)를 가져와서 layoutinflater에 적용시킨다. 이후 inflate를 통해 list_item.xml를 붙여준다.
return CustomViewHolder(view)
}
override fun onBindViewHolder(holder: ProfileAdapter.CustomViewHolder, position: Int) {
//oncreateviewholder를 실제로 바인딩한다, 스크롤할때, 리스트뷰를 사용할때 onBindViewholder가 지속적으로 호출 view에 대해 안정적으로 데이터들을 매치시켜주는 곳
holder.gender.setImageResource(profileList.get(position).gender)
holder.name.text = profileList.get(position).name //positon은 완성했을 때 위치 (0~), 바인드뷰마다 position 별로 연동시켜줌
holder.age.text = profileList.get(position).age.toString() //나이는 int라 settext바로 못함, toString으로 문자열 형태로 변환해야함.
holder.job.text = profileList.get(position).job
}
override fun getItemCount(): Int {
return profileList.size //profilelist의 총길이 리턴
}
class CustomViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { //변수들에 할당 - bindviewholder에서 쓸려고
val gender = itemView.findViewById<ImageView>(R.id.iv_profile) //성별
val name = itemView.findViewById<TextView>(R.id.tv_name) //이름
val age = itemView.findViewById<TextView>(R.id.tv_age) //나이
val job = itemView.findViewById<TextView>(R.id.tv_job) //직업
}
}
번외) 클릭처리까지
onCreateViewHolder 함수에 다음 코드를 더한다.
return CustomViewHolder(view).apply{
itemView.setOnClickListener {
val curPos : Int = adapterPosition
val profile: profiles = profileList.get(curPos)
Toast.makeText(parent.context,"이름 : ${profile.name}\n 나이: ${profile.age} 직업: ${profile.job}", Toast.LENGTH_SHORT).show()
} //itemview는 viewholder에 가지고 있는 view를 의미
}
3. ListView와 RecyclerView의 차이점
안드로이드에서 리스트 형태로 보여주는 것은 ListView 와 RecyclerView 가 있는데 둘의 차이는 다음과 같다.
[참고]https://jitolit.tistory.com/117
RecyclerView | ListView | |
ViewHolder | ViewHolder 패턴 이용 (아이템 재사용) | ViewHolder 패턴 이용할 필요 X |
Item Layout | 가로/세로/지그재그 모두 지원 ->LayoutManager사용 | 세로만 지원, 수동 설정 |
Item Animation | 아이템 애니메이션 처리 클래스 O | 아이템 애니메이션 처리 클래스 X |
Adapter | 데이터 제공을 위해 직접 구현 | 다양한 소스에 대한 어댑터 존재 |
Decoration | 많은 구분선 설정 | 쉽게 구분 가능 |
Click Event | 개별 터치 이벤트 관리O, 클릭 처리 기능 X | 클릭 이벤트에 바인딩 하기위한 인터페이스 존재 |
- ListView는 모든 아이템을 불러오기 때문에 스크롤을 해도 모든 아이템을 유지하며 화면에 보여준다. 하지만 RecycleView는 화면에 보여지는 아이템만 재사용하므로 성능 개선에 좋다.
- 요즘은 대부분은 RecylcerView를 사용하며 ListView에 비해 유연하고 성능이 좋다.
++ ViewHolder 차이
참고
안드로이드 코틀린 앱 만들기 #10 RecyclerView (리사이클러 뷰) - 쉽게 앱 만드는 방법 (현직 개발자 설명) - YouTube
RecyclerView를 Swipe, Drag, Touch하기::Android Studio에서 Kotlin으로#12 - YouTube
'Group Study (2023-2024) > Android 입문' 카테고리의 다른 글
[Android 입문] 5주차 스터디 - RoomDB, SharedPreferences, Datastore (0) | 2023.12.25 |
---|---|
[Android 입문] 4주차 스터디 -Viewpager2, TabLayout, Navigation View (0) | 2023.11.29 |
[Android 입문] 2주차 스터디 -Activity와 Fragment, ViewBinding (0) | 2023.11.13 |
[Android 입문] 1주차 스터디 -View와 Layout (0) | 2023.11.07 |