Android App Track⛺-030

MunkiJeon·2024년 7월 18일

TIL

목록 보기
47/59
post-thumbnail

TIL (Today I Learned)

오늘 공부한거!

  • 뷰바인딩

    • view binding은 이 findViewById를 대체할 수 있는 기능이다
    • findViewById의 문제점
      1. Null 안정성: 개발자가 실수로 유효하지 않은 id를 사용하면 null 오류가 발생할 수 있다.
      2. Type 안정성: textView의 타입을 imageView라고 잘못 적어서 캐스팅하면 cast exception이 발생할 수 있다.
      3. 속도가 상대적으로 느리다.
    • 사용법
      1. gradle 추가
        // 안드로이드 스튜디오 4.0 이상
        android {
          ...
          buildFeatures {
              viewBinding = true
          }
        }
        // 안드로이드 스튜디오 3.6 ~ 4.0(3.6 보다 낮으면 안 됨)
        android {
          ...
          viewBinding {
              enabled true
          }
        }
      2. 액티비티
        2-1. [목차 1-2]에서 보여주었던 클래스를 만들기 위하여 위와 같이 적어준다.
        inflate는 xml에 있는 뷰를 객체화해준다고 생각하면 된다.
        2-2. 원래는 R.layout.activity_main을 넘겨주지만
        이번에는 우리가 생성한 루트 뷰를 넘겨준다.
        2-3. 바인딩된 객체 안에 있는 name, phone, address에 접근하여 사용하면 끝!
          class MainActivity : AppCompatActivity() {
          override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)
              binding = ActivityMainBinding.inflate(layoutInflater)
              setContentView(binding.root)
              binding.textView.text = "안녕"
          }
        }
        Activity 이름Binding Class 이름
        MainActivityActivityMainBinding
        HelloActivityActivityHelloBinding
        XXXActivityActivityXXXBinding
      3. 프래그먼트
        3-1 다른 건 다 똑같은데 다른 점이
        onDestroyView에서 binding에 null을 집어넣어 준다는 것
        why? : 프래그먼트은 뷰보다 오래갑니다.
        프래그먼트의 onDestroyView() 메서드에서 바인딩 클래스 인스턴스에 대한 참조를 모두 정리해야 합니다.
          class BlankFragment : Fragment() {
            private var _binding: FragmentBlankBinding? = null //여기!!
            // This property is only valid between onCreateView and
            // onDestroyView.
            private val binding get() = _binding!!
            override fun onCreateView(
                inflater: LayoutInflater,
                container: ViewGroup?,
                savedInstanceState: Bundle?
            ): View? {
                _binding = FragmentBlankBinding.inflate(inflater, container, false)
                val view = binding.root
                return view
            }
            override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
                super.onViewCreated(view, savedInstanceState)
                binding.textView.text = "안녕"
            }
            override fun onDestroyView() {
                super.onDestroyView()
                _binding = null
            }
        }
  • AdapterView (ListView, GridView)

어댑터 뷰(AdapterView) : 여러 개의 항목을 다양한 형식으로 나열하고 선택 할 수 있는 기능을 제공하는 뷰

  • 리스트 뷰(ListView) : 항목을 수직을 나열시키는 방식
  • 그리드 뷰(GridView) : 항목을 격자 형태로 나열시키는 방식
  • 어댑터(Adapter) : 데이터를 관리하며 데이터 원본과 어댑터뷰(ListView, GridView) 사이의 중계 역할
class [어댑터용도]Adapter(val post: MutableList<데이터 클래스>) : RecyclerView.Adapter<PostAdapter.Holder>() {
//RecyclerView = 어댑터 붙일 뷰의 종류
    fun replaseDecimalFormat(num: Int): String {//1000자리 쉼표 표시 펑션(선택옵션)
        return DecimalFormat("#,###").format(num).toString()
    }

    interface ItemClick {//어댑터 사용시 강제할 펑션 정의(선택옵션)
        fun onClick(view: View, postion: Int)
        fun onPressed(view: View, postion: Int)
    }
    var itemClick: ItemClick? = null

	//데이터들을 담을 뷰 홀더 만들어줌(생성)
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
        val binding =
            ItemRecyclerviewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return Holder(binding)
    }
    //데이터들을 담을 뷰 홀더 구성하고 데이터 넣어줌(정의 & 구성)
    override fun onBindViewHolder(holder: Holder, position: Int) {
        Log.d("onBindViewHolder", position.toString())
        holder.itemView.setOnClickListener { itemClick?.onClick(it, position) }
        holder.itemView.setOnLongClickListener { itemClick?.onPressed(it, position); true }
        holder.postImageView.setImageResource(post[position].picture)
        holder.postImageView.clipToOutline = true
        holder.title.text = post[position].title
        holder.address.text = post[position].address
        holder.cost.text = replaseDecimalFormat(post[position].cost) + "원"
        holder.chat.text = post[position].chat.toString()
        holder.like.text = post[position].like.toString()
        if (post[position].isLike) {
            holder.isike.setImageResource(R.drawable.full_heart)
        } else {
            holder.isike.setImageResource(R.drawable.heart)
        }

    }

    override fun getItemId(position: Int): Long {//아이템 아이디 가져옴(자동생성)
        return position.toLong()
    }

    override fun getItemCount(): Int {//아이템 갯수 샘(자동생성)
        return post.size
    }

	//홀더 정의
    inner class Holder(val binding: ItemRecyclerviewBinding) :
        RecyclerView.ViewHolder(binding.root) {
        // 여기에 필요한 다른 뷰를 추가 가능
        val postImageView = binding.ivItemPic
        val title = binding.tvItemTitle
        val address = binding.tvItemAddress
        val cost = binding.tvItemCost
        val chat = binding.tvChatNum
        val like = binding.tvLikeNum
        val isike = binding.ivItemLike
    }
}

+ 추가로 알게된 용어

  • 로드 뷰 : layout.xml에서 모든 뷰들을 감싸고 있는 뷰

Today Review

profile
공장자동화와 웹 개발을 핥아 먹다 앱 개발로 전향한 개발자의 키보드의 낡은 키캡⛑️

0개의 댓글