refactor: 캐릭터 탭 내부에서 사용하는 Adapter 코드를 ViewBinding 코드로 리팩토링
This commit is contained in:
		@@ -4,6 +4,5 @@ data class Character(
 | 
			
		||||
    val id: String,
 | 
			
		||||
    val name: String,
 | 
			
		||||
    val description: String,
 | 
			
		||||
    val imageUrl: String,
 | 
			
		||||
    val ranking: Int? = null // 인기 캐릭터에서만 사용
 | 
			
		||||
    val imageUrl: String
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,13 @@
 | 
			
		||||
package kr.co.vividnext.sodalive.chat.character
 | 
			
		||||
 | 
			
		||||
import android.annotation.SuppressLint
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.view.LayoutInflater
 | 
			
		||||
import android.view.View
 | 
			
		||||
import android.view.ViewGroup
 | 
			
		||||
import android.widget.ImageView
 | 
			
		||||
import android.widget.LinearLayout
 | 
			
		||||
import android.widget.TextView
 | 
			
		||||
import androidx.recyclerview.widget.RecyclerView
 | 
			
		||||
import kr.co.vividnext.sodalive.R
 | 
			
		||||
import kr.co.vividnext.sodalive.chat.character.Character
 | 
			
		||||
import com.bumptech.glide.Glide
 | 
			
		||||
import kr.co.vividnext.sodalive.databinding.ItemCharacterBinding
 | 
			
		||||
 | 
			
		||||
class CharacterAdapter(
 | 
			
		||||
    private var characters: List<Character> = emptyList(),
 | 
			
		||||
@@ -16,46 +15,47 @@ class CharacterAdapter(
 | 
			
		||||
    private val onCharacterClick: (Character) -> Unit = {}
 | 
			
		||||
) : RecyclerView.Adapter<CharacterAdapter.ViewHolder>() {
 | 
			
		||||
 | 
			
		||||
    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
 | 
			
		||||
        val ivCharacter: ImageView = itemView.findViewById(R.id.iv_character)
 | 
			
		||||
        val tvCharacterName: TextView = itemView.findViewById(R.id.tv_character_name)
 | 
			
		||||
        val tvCharacterDescription: TextView = itemView.findViewById(R.id.tv_character_description)
 | 
			
		||||
        val llRanking: LinearLayout = itemView.findViewById(R.id.ll_ranking)
 | 
			
		||||
        val tvRanking: TextView = itemView.findViewById(R.id.tv_ranking)
 | 
			
		||||
    inner class ViewHolder(
 | 
			
		||||
        private val context: Context,
 | 
			
		||||
        private val binding: ItemCharacterBinding
 | 
			
		||||
    ) : RecyclerView.ViewHolder(binding.root) {
 | 
			
		||||
        @SuppressLint("SetTextI18n")
 | 
			
		||||
        fun bind(character: Character, index: Int) {
 | 
			
		||||
            binding.tvCharacterName.text = character.name
 | 
			
		||||
            binding.tvCharacterDescription.text = character.description
 | 
			
		||||
 | 
			
		||||
            // 순위 표시 여부 결정
 | 
			
		||||
            if (showRanking) {
 | 
			
		||||
                binding.llRanking.visibility = View.VISIBLE
 | 
			
		||||
                binding.tvRanking.text = (index + 1).toString()
 | 
			
		||||
            } else {
 | 
			
		||||
                binding.llRanking.visibility = View.GONE
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Glide.with(context)
 | 
			
		||||
                .load(character.imageUrl)
 | 
			
		||||
                .into(binding.ivCharacter)
 | 
			
		||||
 | 
			
		||||
            binding.root.setOnClickListener { onCharacterClick(character) }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
 | 
			
		||||
        val view = LayoutInflater.from(parent.context)
 | 
			
		||||
            .inflate(R.layout.item_character, parent, false)
 | 
			
		||||
        return ViewHolder(view)
 | 
			
		||||
    }
 | 
			
		||||
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(
 | 
			
		||||
        parent.context,
 | 
			
		||||
        ItemCharacterBinding.inflate(
 | 
			
		||||
            LayoutInflater.from(parent.context),
 | 
			
		||||
            parent,
 | 
			
		||||
            false
 | 
			
		||||
        )
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
 | 
			
		||||
        val character = characters[position]
 | 
			
		||||
 | 
			
		||||
        holder.tvCharacterName.text = character.name
 | 
			
		||||
        holder.tvCharacterDescription.text = character.description
 | 
			
		||||
 | 
			
		||||
        // 순위 표시 여부 결정
 | 
			
		||||
        if (showRanking && character.ranking != null) {
 | 
			
		||||
            holder.llRanking.visibility = View.VISIBLE
 | 
			
		||||
            holder.tvRanking.text = character.ranking.toString()
 | 
			
		||||
        } else {
 | 
			
		||||
            holder.llRanking.visibility = View.GONE
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // TODO: 이미지 로딩 라이브러리 사용 (Glide, Picasso 등)
 | 
			
		||||
        // Glide.with(holder.itemView.context)
 | 
			
		||||
        //     .load(character.imageUrl)
 | 
			
		||||
        //     .into(holder.ivCharacter)
 | 
			
		||||
 | 
			
		||||
        holder.itemView.setOnClickListener {
 | 
			
		||||
            onCharacterClick(character)
 | 
			
		||||
        }
 | 
			
		||||
        holder.bind(characters[position], index = position)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun getItemCount(): Int = characters.size
 | 
			
		||||
 | 
			
		||||
    @SuppressLint("NotifyDataSetChanged")
 | 
			
		||||
    fun updateCharacters(newCharacters: List<Character>) {
 | 
			
		||||
        characters = newCharacters
 | 
			
		||||
        notifyDataSetChanged()
 | 
			
		||||
 
 | 
			
		||||
@@ -72,7 +72,7 @@ class CharacterTabFragment : BaseFragment<FragmentCharacterTabBinding>(
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 전체보기 버튼 클릭 리스너
 | 
			
		||||
        binding.tvFamousCharacterAll.setOnClickListener {
 | 
			
		||||
        binding.tvPopularCharacterAll.setOnClickListener {
 | 
			
		||||
            // 인기 캐릭터 전체보기 처리
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -106,11 +106,11 @@ class CharacterTabFragment : BaseFragment<FragmentCharacterTabBinding>(
 | 
			
		||||
    private fun loadPopularCharacters() {
 | 
			
		||||
        // TODO: 서버에서 인기 캐릭터 데이터 로드
 | 
			
		||||
        val popularCharacters = listOf(
 | 
			
		||||
            Character("1", "캐릭터 이름", "캐릭터 한줄 소개인데 2줄까", "", 1),
 | 
			
		||||
            Character("2", "캐릭터 이름", "캐릭터 한줄 소개인데 2줄까", "", 2),
 | 
			
		||||
            Character("3", "캐릭터 이름", "#태그#태그#태그", "", 3),
 | 
			
		||||
            Character("4", "캐릭터 이름", "캐릭터 한줄 소개인데 2줄까", "", 4),
 | 
			
		||||
            Character("5", "캐릭터 이름", "캐릭터 한줄 소개인데 2줄까", "", 5)
 | 
			
		||||
            Character("1", "캐릭터 이름", "캐릭터 한줄 소개인데 2줄까", ""),
 | 
			
		||||
            Character("2", "캐릭터 이름", "캐릭터 한줄 소개인데 2줄까", ""),
 | 
			
		||||
            Character("3", "캐릭터 이름", "#태그#태그#태그", ""),
 | 
			
		||||
            Character("4", "캐릭터 이름", "캐릭터 한줄 소개인데 2줄까", ""),
 | 
			
		||||
            Character("5", "캐릭터 이름", "캐릭터 한줄 소개인데 2줄까", "")
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        popularCharacterAdapter.updateCharacters(popularCharacters)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,52 +1,58 @@
 | 
			
		||||
package kr.co.vividnext.sodalive.chat.character.curation
 | 
			
		||||
 | 
			
		||||
import android.annotation.SuppressLint
 | 
			
		||||
import android.view.LayoutInflater
 | 
			
		||||
import android.view.View
 | 
			
		||||
import android.view.ViewGroup
 | 
			
		||||
import android.widget.TextView
 | 
			
		||||
import androidx.recyclerview.widget.LinearLayoutManager
 | 
			
		||||
import androidx.recyclerview.widget.RecyclerView
 | 
			
		||||
import kr.co.vividnext.sodalive.R
 | 
			
		||||
import kr.co.vividnext.sodalive.chat.character.CharacterAdapter
 | 
			
		||||
import kr.co.vividnext.sodalive.chat.character.Character
 | 
			
		||||
import kr.co.vividnext.sodalive.chat.character.curation.CurationSection
 | 
			
		||||
import kr.co.vividnext.sodalive.chat.character.CharacterAdapter
 | 
			
		||||
import kr.co.vividnext.sodalive.databinding.ItemCurationSectionBinding
 | 
			
		||||
 | 
			
		||||
class CurationSectionAdapter(
 | 
			
		||||
    private var sections: List<CurationSection> = emptyList(),
 | 
			
		||||
    private val onCharacterClick: (Character) -> Unit = {}
 | 
			
		||||
) : RecyclerView.Adapter<CurationSectionAdapter.ViewHolder>() {
 | 
			
		||||
 | 
			
		||||
    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
 | 
			
		||||
        val tvSectionTitle: TextView = itemView.findViewById(R.id.tv_section_title)
 | 
			
		||||
        val rvCharacters: RecyclerView = itemView.findViewById(R.id.rv_characters)
 | 
			
		||||
    inner class ViewHolder(
 | 
			
		||||
        private val binding: ItemCurationSectionBinding
 | 
			
		||||
    ) : RecyclerView.ViewHolder(binding.root) {
 | 
			
		||||
        fun bind(section: CurationSection) {
 | 
			
		||||
            binding.tvSectionTitle.text = section.title
 | 
			
		||||
 | 
			
		||||
            // 캐릭터 리스트 설정
 | 
			
		||||
            val characterAdapter = CharacterAdapter(
 | 
			
		||||
                characters = section.characters,
 | 
			
		||||
                showRanking = false,
 | 
			
		||||
                onCharacterClick = onCharacterClick
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            binding.rvCharacters.apply {
 | 
			
		||||
                layoutManager = LinearLayoutManager(
 | 
			
		||||
                    context,
 | 
			
		||||
                    LinearLayoutManager.HORIZONTAL,
 | 
			
		||||
                    false
 | 
			
		||||
                )
 | 
			
		||||
                adapter = characterAdapter
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
 | 
			
		||||
        val view = LayoutInflater.from(parent.context)
 | 
			
		||||
            .inflate(R.layout.item_curation_section, parent, false)
 | 
			
		||||
        return ViewHolder(view)
 | 
			
		||||
    }
 | 
			
		||||
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(
 | 
			
		||||
        ItemCurationSectionBinding.inflate(
 | 
			
		||||
            LayoutInflater.from(parent.context),
 | 
			
		||||
            parent,
 | 
			
		||||
            false
 | 
			
		||||
        )
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
 | 
			
		||||
        val section = sections[position]
 | 
			
		||||
 | 
			
		||||
        holder.tvSectionTitle.text = section.title
 | 
			
		||||
 | 
			
		||||
        // 캐릭터 리스트 설정
 | 
			
		||||
        val characterAdapter = CharacterAdapter(
 | 
			
		||||
            characters = section.characters,
 | 
			
		||||
            showRanking = false,
 | 
			
		||||
            onCharacterClick = onCharacterClick
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        holder.rvCharacters.apply {
 | 
			
		||||
            layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
 | 
			
		||||
            adapter = characterAdapter
 | 
			
		||||
        }
 | 
			
		||||
        holder.bind(sections[position])
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun getItemCount(): Int = sections.size
 | 
			
		||||
 | 
			
		||||
    @SuppressLint("NotifyDataSetChanged")
 | 
			
		||||
    fun updateSections(newSections: List<CurationSection>) {
 | 
			
		||||
        sections = newSections
 | 
			
		||||
        notifyDataSetChanged()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,43 +1,43 @@
 | 
			
		||||
package kr.co.vividnext.sodalive.chat.character.recent
 | 
			
		||||
 | 
			
		||||
import android.annotation.SuppressLint
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.view.LayoutInflater
 | 
			
		||||
import android.view.View
 | 
			
		||||
import android.view.ViewGroup
 | 
			
		||||
import android.widget.ImageView
 | 
			
		||||
import android.widget.TextView
 | 
			
		||||
import androidx.recyclerview.widget.RecyclerView
 | 
			
		||||
import kr.co.vividnext.sodalive.R
 | 
			
		||||
import com.bumptech.glide.Glide
 | 
			
		||||
import kr.co.vividnext.sodalive.databinding.ItemRecentCharacterBinding
 | 
			
		||||
 | 
			
		||||
class RecentCharacterAdapter(
 | 
			
		||||
    private var characters: List<RecentCharacter> = emptyList(),
 | 
			
		||||
    private val onCharacterClick: (RecentCharacter) -> Unit = {}
 | 
			
		||||
) : RecyclerView.Adapter<RecentCharacterAdapter.ViewHolder>() {
 | 
			
		||||
 | 
			
		||||
    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
 | 
			
		||||
        val ivProfile: ImageView = itemView.findViewById(R.id.iv_profile)
 | 
			
		||||
        val tvName: TextView = itemView.findViewById(R.id.tv_name)
 | 
			
		||||
    inner class ViewHolder(
 | 
			
		||||
        private val context: Context,
 | 
			
		||||
        private val binding: ItemRecentCharacterBinding
 | 
			
		||||
    ) : RecyclerView.ViewHolder(binding.root) {
 | 
			
		||||
        fun bind(character: RecentCharacter) {
 | 
			
		||||
            binding.tvName.text = character.name
 | 
			
		||||
            Glide.with(context)
 | 
			
		||||
                .load(character.profileImageUrl)
 | 
			
		||||
                .into(binding.ivProfile)
 | 
			
		||||
 | 
			
		||||
            binding.root.setOnClickListener { onCharacterClick(character) }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
 | 
			
		||||
        val view = LayoutInflater.from(parent.context)
 | 
			
		||||
            .inflate(R.layout.item_recent_character, parent, false)
 | 
			
		||||
        return ViewHolder(view)
 | 
			
		||||
    }
 | 
			
		||||
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(
 | 
			
		||||
        parent.context,
 | 
			
		||||
        ItemRecentCharacterBinding.inflate(
 | 
			
		||||
            LayoutInflater.from(parent.context),
 | 
			
		||||
            parent,
 | 
			
		||||
            false
 | 
			
		||||
        )
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
 | 
			
		||||
        val character = characters[position]
 | 
			
		||||
 | 
			
		||||
        holder.tvName.text = character.name
 | 
			
		||||
 | 
			
		||||
        // TODO: 이미지 로딩 라이브러리 사용 (Glide, Picasso 등)
 | 
			
		||||
        // Glide.with(holder.itemView.context)
 | 
			
		||||
        //     .load(character.profileImageUrl)
 | 
			
		||||
        //     .into(holder.ivProfile)
 | 
			
		||||
 | 
			
		||||
        holder.itemView.setOnClickListener {
 | 
			
		||||
            onCharacterClick(character)
 | 
			
		||||
        }
 | 
			
		||||
        holder.bind(characters[position])
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun getItemCount(): Int = characters.size
 | 
			
		||||
 
 | 
			
		||||
@@ -105,7 +105,7 @@
 | 
			
		||||
                    android:textSize="24sp" />
 | 
			
		||||
 | 
			
		||||
                <TextView
 | 
			
		||||
                    android:id="@+id/tv_famous_character_all"
 | 
			
		||||
                    android:id="@+id/tv_popular_character_all"
 | 
			
		||||
                    android:layout_width="wrap_content"
 | 
			
		||||
                    android:layout_height="wrap_content"
 | 
			
		||||
                    android:fontFamily="@font/pretendard_regular"
 | 
			
		||||
@@ -121,8 +121,7 @@
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:layout_marginTop="16dp"
 | 
			
		||||
                android:clipToPadding="false"
 | 
			
		||||
                android:paddingStart="24dp" />
 | 
			
		||||
 | 
			
		||||
                android:paddingHorizontal="24dp" />
 | 
			
		||||
        </LinearLayout>
 | 
			
		||||
 | 
			
		||||
        <!-- 신규 캐릭터 섹션 -->
 | 
			
		||||
@@ -167,7 +166,7 @@
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:layout_marginTop="16dp"
 | 
			
		||||
                android:clipToPadding="false"
 | 
			
		||||
                android:paddingStart="24dp" />
 | 
			
		||||
                android:paddingHorizontal="24dp" />
 | 
			
		||||
 | 
			
		||||
        </LinearLayout>
 | 
			
		||||
 | 
			
		||||
@@ -177,7 +176,5 @@
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_marginBottom="24dp" />
 | 
			
		||||
 | 
			
		||||
    </LinearLayout>
 | 
			
		||||
 | 
			
		||||
</androidx.core.widget.NestedScrollView>
 | 
			
		||||
		Reference in New Issue
	
	Block a user