[Android] ListView

 ๐Ÿ’ก ์•ˆ๋“œ๋กœ์ด๋“œ์—์„œ List๋ฅผ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ListView์— ๋Œ€ํ•˜์—ฌ ํ•™์Šตํ•˜์˜€์Šต๋‹ˆ๋‹ค !

 

ListView

  • ๋ฆฌ์ŠคํŠธ๋ทฐ๋Š” ๋ฐ์ดํ„ฐ ๋ชฉ๋ก์„ ๋‚˜์—ดํ•˜์—ฌ ํ™”๋ฉด์— ํ‘œ์‹œํ•˜๋Š” ๋ทฐ ๊ทธ๋ฃน์˜ ํ•œ ์ข…๋ฅ˜์ž…๋‹ˆ๋‹ค.
  • ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์•„์ดํ…œ ์ค‘์— ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” Selection Widget ์ž…๋‹ˆ๋‹ค.
  • ListView๋ฅผ ํšจ์œจ์ ์œผ๋กœ ํ™œ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” convertView์™€ ViewHolder ํŒจํ„ด์„ ํšจ์œจ์ ์œผ๋กœ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.
  • ์ด ํŒจํ„ด์„ ํ†ตํ•ด์„œ ๋ฆฌ์ŠคํŠธ ์•„์ดํ…œ์„ ์žฌ์‚ฌ์šฉํ•˜์—ฌ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

converView

  • ListView์—์„œ ๊ธฐ์กด์˜ ๋ทฐ๋ฅผ ์žฌ์‚ฌ์šฉํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ์ž…๋‹ˆ๋‹ค.
  • adapter์—์„œ ์ด์ „ ๋ทฐ๊ฐ€ ์žฌ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•  ๊ฒฝ์šฐ ๊ทธ ๋ทฐ์˜ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฆฌ์ŠคํŠธ๊ฐ€ ์Šคํฌ๋กค ๋  ๋•Œ ์ƒˆ๋กœ์šด ์•„์ดํ…œ์„ ํ‘œ์‹œํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ๋ทฐ๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ , ์ด๋ฏธ ์‚ฌ์šฉ๋œ ๋ทฐ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜์—ฌ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•ฉ๋‹ˆ๋‹ค.

ViewHolder

  • Inflate๋ฅผ ์ตœ์†Œํ™”ํ•˜๊ธฐ ์œ„ํ•ด์„œ view๋“ค์˜ ๊ฐ ์š”์†Œ์— ๋ฐ”๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ์ €์žฅํ•ด๋‘๊ณ  ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.
  • ๋ทฐ์˜ ์ฐธ์กฐ๋ฅผ ์ €์žฅํ•˜์—ฌ ๋งค๋ฒˆ findViewById()๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
  • convertView๊ฐ€ ์žฌ์‚ฌ์šฉ๋  ๋•Œ ํšจ์œจ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”์ธ๋”ฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.
  • RecyclerView์™€ ๋‹ค๋ฅด๊ฒŒ ListView๋Š” Viewholder ํŒจํ„ด์ด ์„ ํƒ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค.

inflate()

  • ๋ถ€ํ’€๊ฒŒ ํ•˜๋‹ค๋Š” ๋œป์œผ๋กœ, ์•ˆ๋“œ๋กœ์ด๋“œ์—์„œ๋Š” xml์— ํ‘œ์‹œ๋œ ๋ ˆ์ด์•„์›ƒ๋“ค์„ ๋ฉ”๋ชจ๋ฆฌ์— ๊ฐ์ฒดํ™” ์‹œํ‚ค๋Š” ํ–‰๋™์„ ๋งํ•ฉ๋‹ˆ๋‹ค.
  • xml์˜ ์ฝ”๋“œ๋ฅผ ๊ฐ์ฒดํ™”ํ•˜์—ฌ ์ฝ”๋“œ์—์„œ UI ์š”์†Œ ๋“ฑ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด inflateํ•˜๋ฉฐ, setContentView() ํ•จ์ˆ˜์—์„œ ํ•ด๋‹น ๋™์ž‘์ด ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค.

Adapter

  • ListView์— ์‚ฌ์šฉ์ž๊ฐ€ ์ •์˜ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Adapter๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์–ด๋Œ‘ํ„ฐ๋Š” ์‚ฌ์šฉ์ž์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„ ๋ทฐ๋ฅผ ์ƒ์„ฑํ•ด์ฃผ๋Š” ๊ฐ์ฒด๋กœ ListView์™€๋Š” ๋…๋ฆฝ์ ์œผ๋กœ ๋™์ž‘ํ•˜๋Š” ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.
  • ListView๋Š” Adapter๋กœ๋ถ€ํ„ฐ ์ƒ์„ฑ๋œ ๋ทฐ๋ฅผ ๋ฐ›์•„ ListView์˜ ํ•œ ํ•ญ๋ชฉ์œผ๋กœ ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค.

  • Adapter๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ViewHolder ํŒจํ„ด์„ ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  private class MyListAdapter(context: Context, private val data: List<String>) : BaseAdapter() {

        private val inflater: LayoutInflater = LayoutInflater.from(context)

        override fun getCount(): Int = data.size

        override fun getItem(position: Int): String = data[position]

        override fun getItemId(position: Int): Long = position.toLong()

        override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
            val view: View
            val holder: ViewHolder

            if (convertView == null) {
                // convertView๊ฐ€ null์ธ ๊ฒฝ์šฐ ์ƒˆ๋กœ์šด ๋ทฐ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ViewHolder๋ฅผ ์„ค์ •
                view = inflater.inflate(R.layout.list_item, parent, false)
                holder = ViewHolder()
                holder.textView = view.findViewById(R.id.itemTextView)
                view.tag = holder
            } else {
                // convertView๊ฐ€ ์žฌ์‚ฌ์šฉ๋˜๋Š” ๊ฒฝ์šฐ ViewHolder๋ฅผ ๊ฐ€์ ธ์˜ด
                view = convertView
                holder = view.tag as ViewHolder
            }

            // ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ
            holder.textView?.text = getItem(position)

            return view
        }

        // ViewHolder ํŒจํ„ด์„ ์œ„ํ•œ ๋‚ด๋ถ€ ํด๋ž˜์Šค
        private class ViewHolder {
            var textView: TextView? = null
        }
    }

converView ์žฌ์‚ฌ์šฉ

  • convertView๊ฐ€ null ์ผ ๋•Œ๋งŒ ์ƒˆ๋กœ์šด ๋ทฐ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ convertView๋ฅผ ์žฌ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ์ด๋กœ ์ธํ•ด ๋ฆฌ์ŠคํŠธ๊ฐ€ ์Šคํฌ๋กค ๋  ๋•Œ ์ƒˆ๋กœ์šด ๋ทฐ๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์„ฑ๋Šฅ์ด ํ–ฅ์ƒ๋ฉ๋‹ˆ๋‹ค.

ViewHolder ํŒจํ„ด

  • ViewHolder ํด๋ž˜์Šค๋Š” ๋ฆฌ์ŠคํŠธ ์•„์ดํ…œ์˜ ๋ทฐ ์ฐธ์กฐ๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
  • ๋ทฐ๋ฅผ ์ฒ˜์Œ ์ƒ์„ฑํ•  ๋•Œ ViewHolder๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ด ๊ฐ์ฒด๋ฅผ converView์˜ ํƒœ๊ทธ๋กœ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
  • ์ด ํ›„์— converView๊ฐ€ ์žฌ์‚ฌ์šฉ๋  ๋•Œ, ViewHolder ๊ฐ์ฒด๋ฅผ ์žฌ์‚ฌ์šฉํ•˜์—ฌ findViewById() ํ˜ธ์ถœ์„ ํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ

  • getItem(positon)์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ViewHolder์˜ textView์— ์„ค์ •ํ•จ์œผ๋กœ์จ ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

ListView์˜ ํ•œ๊ณ„

  • ๋ฆฌ์ŠคํŠธ ๋ทฐ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ํ•œ๊ณ„์ ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์ œํ•œ๋œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ œ๊ณต
    • ๋Œ€๊ทœ๋ชจ ๋ฐ์ดํ„ฐ๋‚˜ ๋ณต์žกํ•œ ๋ ˆ์ด์•„์›ƒ์—์„œ ์„ฑ๋Šฅ ์ €ํ•˜
    • ์ œํ•œ๋œ ๋ทฐ ํƒ€์ž…๊ณผ ์–ด๋Œ‘ํ„ฐ์˜ ๋ณต์žก์„ฑ ์ฆ๊ฐ€
    • ๋ถ€๋ถ„ ๊ฐฑ์‹ ์˜ ์–ด๋ ค์›€์œผ๋กœ ๊ฐ„๋‹จํ•œ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ์•Œ๋ฆผ๋งŒ ๊ฐ€๋Šฅ (notifyDataSetChanged())
  • ์ด๋ฅผ ๋ณด์™„ํ•˜๊ธฐ ์œ„ํ•ด์„œ RecyclerView๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ •๋ฆฌ

  • ListView์˜ ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•๊ณผ converView, ViewHolder ํŒจํ„ด์— ๋Œ€ํ•˜์—ฌ ํ•™์Šตํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  • ์ด ํŒจํ„ด์„ ํ†ตํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • RecyclerView๋ฅผ ํ™œ์šฉํ•œ๋‹ค๋ฉด ListView์˜ ํ•œ๊ณ„๋ฅผ ๋ณด์™„ํ•˜๊ณ  ๋” ๋†’์€ ์œ ์—ฐ์„ฑ๊ณผ ์„ฑ๋Šฅ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ฐ„๋‹จํ•œ ๋ชฉ๋ก์„ ๋น ๋ฅด๊ฒŒ ๊ตฌํ˜„ํ•˜๊ณ ์ž ํ•  ๋•Œ๋Š” ListView๊ฐ€ ์œ ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์œ ์ง€๋ณด์ˆ˜์™€ ํ™•์žฅ์„ฑ์„ ๊ณ ๋ คํ•œ๋‹ค๋ฉด RecyclerView๋ฅผ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ 

https://medium.com/android-develop-android/android๊ฐœ๋ฐœ-5-listview๋ฅผ-์ด์šฉํ•œ-๋ฆฌ์ŠคํŠธ๋งŒ๋“ค๊ธฐ-215b9693d33b

https://lktprogrammer.tistory.com/163