๊นจ์•Œ ๊ฐœ๋… ๐Ÿ“‘/Android

[Android] RecyclerView - Adapter์— ์ธ์ž(Argument) ์ „๋‹ฌ

interfacer_han 2024. 2. 3. 14:24

#1 ์ด์ „ ๊ธ€

 

[Android] RecyclerView - ๊ธฐ์ดˆ

#1 ListView vs RecyclerView ํ™”๋ฉด์— ์š”์†Œ(Item)์„ 100๊ฐœ ํ‘œํ˜„ํ•œ๋‹ค๊ณ  ํ•ด๋ณด์ž. ListView๋‚˜ GridView ๋“ฑ์˜ ์ „ํ†ต์ ์ธ Container Widget๋“ค์€ ์ด 100๊ฐœ์˜ ์•„์ดํ…œ์„ ๋ชจ๋‘ ๋ถˆ๋Ÿฌ์˜จ(load)๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ™”๋ฉด์„ ์Šคํฌ๋กคํ•˜๋ฉด ๋ฏธ๋ฆฌ Load๋˜

kenel.tistory.com

์ด์ „ ๊ธ€์˜ ์™„์„ฑ๋œ ์•ฑ์ด, Adapter๊ฐ€ ์ธ์ž(Argument)๋ฅผ ์ „๋‹ฌ๋ฐ›๋„๋ก ์ˆ˜์ •ํ•ด๋ณธ๋‹ค. ์ถ”๊ฐ€๋กœ, ViewHolder์— ํด๋ฆญ ๋ฆฌ์Šค๋„ˆ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ์˜ˆ์‹œ์™€ ๊ทธ ํด๋ฆญ ๋ฆฌ์Šค๋„ˆ ๋˜ํ•œ ์ธ์ž(Argument)๋กœ ์ „๋‹ฌํ•˜๋Š” ์ฝ”๋“œ๋„ ์‚ดํŽด๋ณธ๋‹ค.
 

#2 Adapter๊ฐ€ ์ธ์ž๋ฅผ ์ „๋‹ฌ๋ฐ›๊ฒŒ ๋งŒ๋“ค๊ธฐ

#2-1 Menu.kt ๋งŒ๋“ค๊ธฐ

// package com.example.argumenttoadapter

data class Menu(val name: String, val price: Int)

๋จผ์ €, Adapter์— ์ธ์ž(Argument)๋กœ์„œ ์ „๋‹ฌ๋  data class๋ฅผ ๋งŒ๋“ ๋‹ค.
 

#2-2 MainActivity.kt ์ˆ˜์ •

...

class MainActivity : AppCompatActivity() {
    val burgers = listOf<Menu>(
        Menu("Classic Cheeseburger", 6800),
        Menu("Bacon Deluxe Burger", 7800),
        Menu("BBQ Ranch Burger", 5800),
        Menu("Mushroom Swiss Burger", 6700),
        Menu("Double Stack Burger", 9800),
        Menu("Spicy Chicken Burger", 7900),
        Menu("Crispy Chicken Burger", 6800),
        Menu("Grilled Chicken Club", 9700),
        Menu("Veggie Burger Deluxe", 6800),
        Menu("Hawaiian Teriyaki Burger", 8900),
        Menu("Philly Cheese Steak Burger", 6200),
        Menu("Western BBQ Burger", 7300),
        Menu("Jalapeno Pepper Jack Burger", 7900),
        Menu("Turkey Avocado Burger", 6700),
        Menu("Black Bean Burger", 7600),
        Menu("Bacon Jalapeno Burger", 6700),
        Menu("Ultimate BBQ Bacon Burger", 6700),
        Menu("Chicken Bacon Ranch Burger", 6700),
        Menu("Chipotle Guacamole Burger", 6700),
        Menu("Breakfast Burger", 4700),
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        recyclerView.adapter = MyRecyclerViewAdapter(burgers)
    }
}

Menu ๊ฐ์ฒด 20๊ฐœ๋ฅผ ๋‹ด์€ List๋ฅผ ๋งŒ๋“ค๊ณ , Adapter์˜ ์ƒ์„ฑ์ž ์•ˆ์— ๋„ฃ์–ด์ค€๋‹ค.
 

#2-3 MyRecyclerViewAdapter.kt ์ˆ˜์ •

..

class MyRecyclerViewAdapter(val menus: List<Menu>) : RecyclerView.Adapter<MyViewHolder>() {
    ...

    override fun getItemCount(): Int {
        return menus.size
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
/*
        // ๋‚˜์˜์ง€ ์•Š์ง€๋งŒ ๊ฐ์ฒด์ง€ํ–ฅ์ ์ด์ง€๋Š” ์•Š์€ ์ฝ”๋“œ
        val menu = menus[position]
        holder.textItem.text = "${menu.name}\n${menu.price}โ‚ฉ"
*/
        // ๊ฐ์ฒด์ง€ํ–ฅ์ ์ธ ์ฝ”๋“œ
        holder.bind(menus[position])
    }
}

class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
    val textItem: TextView = view.findViewById(R.id.textItem)

    fun bind(menu: Menu) {
        textItem.text = "${menu.name}\n${menu.price}โ‚ฉ"
    }
}

Adapter๊ฐ€ List<Menu>๋ฅผ ๋ฐ›๋„๋ก ์ƒ์„ฑ์ž๋ฅผ ์ˆ˜์ •ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น List<Menu> ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ Adapter์˜ ํ”„๋กœํผํ‹ฐ๋กœ์„œ ํ™œ์šฉํ•  ๊ฒƒ์ด๋ฏ€๋กœ val ํ‚ค์›Œ๋“œ๋„ ๋ถ™์ธ๋‹ค.
 
getItemCount()๊ฐ€ ์ธ์ž๋กœ ๋ฐ›์€ ๋ฆฌ์ŠคํŠธ์˜ ๊ธธ์ด๋ฅผ ์ถœ๋ ฅํ•˜๊ฒŒ ์ˆ˜์ •ํ•œ๋‹ค. ViewHolder์— ์ž๊ธฐ ์ž์‹ ์„ Bindํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ๋งŒ๋“ค๊ณ ,
onBindViewHolder์—์„  position ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ด์šฉํ•ด ViewHolder.Bind()๋ฅผ ์ž‘๋™์‹œํ‚ค๊ฒŒ ๋งŒ๋“ ๋‹ค.
 

#2-4 ์ž‘๋™ ํ™•์ธ

 

#3 ViewHolder์— ํด๋ฆญ ๋ฆฌ์Šค๋„ˆ ๋‹ฌ๊ธฐ

#3-1 ๊ธฐ๋ณธ์ ์ธ ๊ตฌํ˜„

...

class MyRecyclerViewAdapter(val menus: List<Menu>) : RecyclerView.Adapter<MyViewHolder>() {
    ...
}

class MyViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
    val textItem: TextView = view.findViewById(R.id.textItem)

    fun bind(menu: Menu) {
        textItem.text = "${menu.name}\n${menu.price}โ‚ฉ"

        view.setOnClickListener {
            Toast.makeText(
                view.context, "Selected Menu is ${menu.name}", Toast.LENGTH_LONG
            ).show()
        }
    }
}

MyViewHolder์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ view๋ฅผ MyViewHolder์˜ ํ”„๋กœํผํ‹ฐ๋กœ ํ™œ์šฉํ•  ๊ฒƒ์ด๋ฏ€๋กœ val์„ ๋ถ™์ธ๋‹ค. ๊ทธ๋ฆฌ๊ณ  MyViewHolder.bind()์— ํด๋ฆญ ๋ฆฌ์Šค๋„ˆ๋ฅผ ๋“ฑ๋กํ•œ๋‹ค.
 

#3-2 ์ธ์ž(Argument)๋กœ ์ „๋‹ฌ๋ฐ›์•„ ๊ตฌํ˜„

...

class MainActivity : AppCompatActivity() {
    ...

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        recyclerView.adapter = MyRecyclerViewAdapter(burgers) { menu: Menu -> itemClicked(menu) }
    }

    private fun itemClicked(menu: Menu) {
        Toast.makeText(
            this, "Selected Menu is ${menu.name}", Toast.LENGTH_LONG
        ).show()
    }
}

#3-1์—์„œ ๋งŒ๋“ค์—ˆ๋˜ Toast ๋ฉ”์‹œ์ง€ ์ฝ”๋“œ๋ฅผ itemClicked()๋ผ๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ๋งŒ๋“ค์–ด ๊ทธ ์•ˆ์œผ๋กœ ์˜ฎ๊ธด๋‹ค. ๊ทธ๋ฆฌ๊ณ  #2-2์—์„œ์™€ ๊ฐ™์€ ๋งฅ๋ฝ์œผ๋กœ Adapter์˜ ์ƒ์„ฑ์ž์— itemClicked()๋ฅผ ๋žŒ๋‹ค์‹์˜ ํ˜•ํƒœ๋กœ ๋„ฃ๋Š”๋‹ค. ์ฝ”ํ‹€๋ฆฐ์—์„œ ํ•จ์ˆ˜๋Š” ์ผ๊ธ‰ ๊ฐ์ฒด์ด๊ธฐ์— ์ธ์ž(Argument)๋กœ์„œ ์ „๋‹ฌ๋  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ๋‹ค. ๋žŒ๋‹ค์‹์— ๊ด€ํ•œ ๋ฌธ๋ฒ•์€ ์—ฌ๊ธฐ์—์„œ ํ™•์ธํ•˜์ž. ๋žŒ๋‹ค์‹์ด ์ƒ์„ฑ์ž์˜ ๋งˆ์ง€๋ง‰ ์ธ์ž์ด๊ธฐ์—, ํŽธ์˜์„ฑ ๋ฌธ๋ฒ•(์ด ๋งํฌ์˜ #2-5 ์ฐธ์กฐ)์„ ์ ์šฉํ•ด ๊ด„ํ˜ธ ๋ฐ–์œผ๋กœ ๋บ€ ๋ชจ์Šต์ด๋‹ค.
 

...

class MyRecyclerViewAdapter(val menus: List<Menu>, val clickListener: (Menu) -> Unit) :
    ...

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        ...
        holder.bind(menus[position], clickListener)
    }
}

class MyViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
    val textItem: TextView = view.findViewById(R.id.textItem)

    fun bind(menu: Menu, clickListener: (Menu) -> Unit) {
        textItem.text = "${menu.name}\n${menu.price}โ‚ฉ"

        view.setOnClickListener {
            clickListener(menu)
        }
    }
}

Adapter๊ฐ€ (Menu) -> Unit ํ˜• ํ•จ์ˆ˜๋ฅผ ๋ฐ›๋„๋ก ์ƒ์„ฑ์ž๋ฅผ ์ˆ˜์ •ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น (Menu) -> Unitํ˜• ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ Adapter์˜ ํ”„๋กœํผํ‹ฐ๋กœ์„œ ํ™œ์šฉํ•  ๊ฒƒ์ด๋ฏ€๋กœ val ํ‚ค์›Œ๋“œ๋„ ๋ถ™์ธ๋‹ค.
 
MyViewHolder.bind()๊ฐ€ MyRecyclerViewAdapter.clickListener๋ฅผ ๋ฐ›๋„๋ก ์ˆ˜์ •ํ•˜๊ณ  view.setOnClickListener์— ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ํ• ๋‹นํ•œ๋‹ค.
 

#3-3 ์ž‘๋™ ํ™•์ธ (#3-1 ๋ฐ #3-2)

 

#4 ์š”์•ฝ

์ฝ”ํ‹€๋ฆฐ์˜ ํ•จ์ˆ˜๊ฐ€ ์ผ๊ธ‰ ๊ฐ์ฒด์ž„์„ ์•Œ๊ณ  ์ดํ•ดํ•ด์•ผ, ์ œ๋Œ€๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
 

#5 ์™„์„ฑ๋œ ์•ฑ

 

android-practice/recycler-view/ArgumentToAdapter at master ยท Kanmanemone/android-practice

Contribute to Kanmanemone/android-practice development by creating an account on GitHub.

github.com