Group Study (2023-2024)/Android 입문

[Android 입문] 3주차 스터디 -ListView, RecyclerView, ListView와 RecyclerView의 차이점

샘스카이브 2023. 11. 20. 23:13

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 차이

[그림참고]

[참고] https://velog.io/@keepcalm/ListView%EC%99%80-RecyclerView%EC%9D%98-%EC%B0%A8%EC%9D%B4-View-Binding-View-Holder


참고

안드로이드 코틀린 앱 만들기 #5 ListView (리스트 뷰) - 쉽게 앱 만드는 방법 (현직 개발자 설명) , android studio easy tutorial - YouTube 

안드로이드 코틀린 앱 만들기 #10 RecyclerView (리사이클러 뷰) - 쉽게 앱 만드는 방법 (현직 개발자 설명) - YouTube

RecyclerView를 Swipe, Drag, Touch하기::Android Studio에서 Kotlin으로#12 - YouTube