안드로이드 공부/ ListView

yellow·2021년 6월 1일
0

안드로이드 공부

목록 보기
20/28

ListView

  • 앞서 addView 방식으로 ListView를 구성하는 방식 대신, view component인 <ListView>를 써서 ListView를 만드는 방법
  • inflater로 item view를 만들고 container에 그 item을 붙이는 과정을 Adapter가 해준다.

📎 addView와 ListView 차이점

✔ addView

: 리스트 item의 개수와 상관 없이 한번에 다 그린다.

✔ ListView

: 보여지는 부분 + α를 한번에 그리고, 필요한 경우에 더 그린다.
  예를 들어, 리스트에 아이템이 많아서 한 화면 안에 모든 아이템을 담지 못하는 경우에 일단 현재 화면에 띄울 수 있는 부분만 그려놓고 나중에 스크롤을 내렸을 때 다른 부분을 더 그린다.

📎 ListView 예제

1. Activity에 리스트뷰를 담을 container 생성

  • <ListView>를 이용
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ListViewActivity">

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

2. Item을 담을 xml 생성

  • addView 방식과 동일

3. Activity에 Car 클래스를 생성해서 Item List 만들기

  • addView 방식과 동일

4. Adapter 만들기

getCount()

: 가지고 있는 item의 개수 (어댑터가 화면에 총 몇개의 아이템을 보여줄지 정할 때 참고함)

getItem(position: Int)

: position번째 item 받기

getItemId(position: Int)

: position번째 item에 Id 부여

getView(position: Int, convertView: View?, parent: ViewGroup?)

: 화면에 보여질 각각의 item을 위한 view 만들기

class ListViewAdapter(
    val carForList: ArrayList<Car>,
    val layoutInflater: LayoutInflater
) : BaseAdapter(){


    override fun getCount(): Int {
        return carForList.size
    }

    override fun getItem(position: Int): Any {
       return carForList.get(position)
    }

    override fun getItemId(position: Int): Long {
      return position.toLong()
    }

    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {

        // item_view.xml을 메모리에 객체화, 변수에 담기
        val view = layoutInflater.inflate(R.layout.item_view, null)

        // item view에 내용 추가
        val carNameView = view.findViewById<TextView>(R.id.car_name)
        val carEngineView = view.findViewById<TextView>(R.id.car_engine)

        carNameView.text = carForList.get(position).name
        carEngineView.text = carForList.get(position).engine

        // 만든 view 리턴
        return view
    }
}

5. ListView에 item들 추가하기

val layoutInflater = LayoutInflater.from(this)
val adapter = ListViewAdapter(carList, layoutInflater)

val listView = findViewById<ListView>(R.id.listView)
// 리스트뷰에 아이템들 추가
listView.adapter = adapter

📎 한 아이템을 클릭했을 때 리스너를 장착하는 법

  • setOnItemListener 사용
  • 예시 ) 아이템을 클릭하면 해당 아이템의 정보를 toast 메세지로 띄우기
listView.setOnItemClickListener { parent, view, position, id ->
    val carName = (adapter.getItem(position) as Car).name
    val carEngine = (adapter.getItem(position) as Car).engine

    Toast.makeText(this, "자동차 이름: " + carName + ", 엔진: " + carEngine,Toast.LENGTH_SHORT).show()
}

ListView의 속성

  • 위의 사진에서 보면 addView 방식과는 다르게, ListView에서 기본으로 구분선을 가지고 있다.(divider)
  • ListView의 속성 divider와 dividerHeight로 divider의 굵기 등을 변경할 수 있다.
  • 이 외에도 ListView는 다른 많은 속성을 가지고 있는데, 필요할 때 검색해서 사용해보도록 하자.

📎 ListView 성능 향상시키기

  • ViewHolder를 이용
  • 리스트에 item이 많은 경우 getView()에서의 findViewById를 많이 호출하기 때문에 시스템에 과부하가 걸릴 수가 있다. 따라서 뷰를 뷰홀더에 담아놓고 재사용하는 방법을 이용해서 ListView의 성능을 향상시킨다.
  • convertView(재활용되는 view)는 최초 한번만 생성된다. 따라서 최초로 호출되는 getView()의 convertView는 null인 특성을 이용해서 (convertView == null)인 경우에만 레이아웃을 inflate하고 그 레이아웃 안에 있는 view들을 findViewById()로 찾아 ViewHolder에 저장하여 그 홀더를 tag에 저장한다.
  • 그리고 최초 이후에 호출되는 getView()의 경우에는 이미 만들어진 view를 tag를 통해 불러와서 사용하기 때문에 view를 재사용하면서 성능이 좋아진다.
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {

        val view: View
        val holder: ViewHolder

        // 재사용할 뷰가 없다면
        if (convertView == null){
            // 레이아웃을 inflate한다.
            view = layoutInflater.inflate(R.layout.item_view, null)

            // 뷰홀더 생성
            holder = ViewHolder()

            // 인플레이트 한 레이아웃 안에 있는 뷰를 만들어서 뷰홀더에 넣는다.
            holder.carName = view.findViewById(R.id.car_name)
            holder.carEngine = view.findViewById(R.id.car_engine)

            // tag에 홀더를 저장
            view.tag = holder
        }else{
            // tag로 뷰를 불러와서 대체
            holder = convertView.tag as ViewHolder
            view = convertView
        }
        holder.carName?.text  = carForList[position].name
        holder.carEngine?.text  = carForList[position].engine

        return view
}
profile
할 수 있어! :)

0개의 댓글