https://goni95.tistory.com/173
1️⃣ListView
많은 수의 데이터 집합을 개별 Item 단위로 구성해 스크롤 가능한 리스트로 화면에 출력하는 ViewGroup 입니다.
리스트뷰는 화면에 보여지는 개수만큼 View를 그려놓고 그것을 View 배열이 관리하여 리스트뷰의 포지션에 따라 이 배열의 위치가 바뀌는 구조로 재활용 합니다.
화면에 새로운 Item을 표시할 때 마다 Adapter의 getView() 메소드가 호출되고 매개변수로 전달되는 convertView가 null이 아니라면 View를 재사용하는 경우 입니다.
ListView를 구현해보겠습니다.
data class Data(val profile: Int, val name: String)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".CustomListViewActivity">
<ListView
android:id="@+id/listView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
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="wrap_content"
android:layout_margin="10dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/listview_imageview"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@mipmap/ic_launcher"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0"
tools:ignore="MissingConstraints" />
<TextView
android:id="@+id/listview_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="입력해주세요"
android:textSize="15sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/listview_imageview"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
class CustomListViewActivity : AppCompatActivity() {
private var dataList = arrayListOf(
Data(R.mipmap.ic_launcher,"0번"),
Data(R.mipmap.ic_launcher_round,"1번"),
Data(R.mipmap.ic_launcher,"2번"),
Data(R.mipmap.ic_launcher_round,"3번"),
Data(R.mipmap.ic_launcher,"4번"),
Data(R.mipmap.ic_launcher_round,"5번"),
Data(R.mipmap.ic_launcher,"6번"),
Data(R.mipmap.ic_launcher_round,"7번"),
Data(R.mipmap.ic_launcher,"8번"),
Data(R.mipmap.ic_launcher_round,"9번"),
Data(R.mipmap.ic_launcher,"10번"),
Data(R.mipmap.ic_launcher_round,"11번"),
Data(R.mipmap.ic_launcher,"12번"),
Data(R.mipmap.ic_launcher_round,"13번"),
Data(R.mipmap.ic_launcher,"14번"),
Data(R.mipmap.ic_launcher_round,"15번"))
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_custom_list_view)
listView.adapter = CustomAdapter(dataList)
listView.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id ->
val selectItem = parent.getItemAtPosition(position) as Data
Toast.makeText(this, selectItem.name, Toast.LENGTH_SHORT).show()
}
}
}
class CustomAdapter (private val dataList: List<Data>) : BaseAdapter() {
override fun getCount(): Int = dataList.size
override fun getItem(position: Int) = dataList[position]
override fun getItemId(position: Int) = position.toLong()
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val view = convertView ?: LayoutInflater.from(parent?.context).inflate(R.layout.item, parent, false)
val profile = view.findViewById<ImageView>(R.id.listview_imageview)
val name = view.findViewById<TextView>(R.id.listview_textview)
val data = dataList[position]
profile.setImageResource(data.profile)
name.text = data.name
return view
}
}
Item View를 inflate해 객체화하고, inflating된 Item View 객체에서 findViewById()를 통해 원하는 View를 찾아 데이터를 Binding 해주는 작업은 데이터가 많아질수록 findViewById()의 지속적인 호출로 인해 느려지는 현상이 발생하게 됩니다.
이를 해결하기 위해서 ListView에서 getView() 메서드의 convertView를 통해 inflating하는 작업을 줄였지만 데이터의 Binding을 위해 findViewById()를 계속 호출해주는 작업은 변함없기 때문에 ViewHolder 패턴을 통해 한번 연결한 데이터를 저장하여 다시 findViewById()를 통해 View를 찾아올 필요가 없어집니다.
아래에서 ViewHolder 패턴을 강제하는 RecyclerView를 알아보겠습니다.
2️⃣RecycerView
많은 수의 데이터 집합을 개별 Item 단위로 구성해 스크롤 가능한 리스트로 화면에 출력하는 ViewGroup 입니다.
리사이클러뷰는 처음 화면에 보이는 데이터 목록이 10개라면 13~15개 정도의 View 객체를 담고있는 ViewHolder를 생성하고, 스크롤 시 최상단에 있던 ViewHolder를 재사용해 데이터를 Binding하여 데이터 목록의 가장 아래로 이동시켜 다시 화면에 표시될 수 있도록 합니다.
RecyclerView를 구현해보겠습니다.
data class Data(val profile: Int, val name: String)
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
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="wrap_content"
android:layout_margin="10dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/listview_imageview"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@mipmap/ic_launcher"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0"
tools:ignore="MissingConstraints" />
<TextView
android:id="@+id/listview_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="입력해주세요"
android:textSize="15sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/listview_imageview"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
class CustomRecyclerView : AppCompatActivity() {
//custeomAdapter에 전달할 DataList를 Data의 형식에 맞게 생성
private var dataList = arrayListOf(
Data(R.mipmap.ic_launcher,"0번"),
Data(R.mipmap.ic_launcher,"1번"),
Data(R.mipmap.ic_launcher,"2번"),
Data(R.mipmap.ic_launcher,"3번"),
Data(R.mipmap.ic_launcher,"4번"),
Data(R.mipmap.ic_launcher,"5번"),
Data(R.mipmap.ic_launcher,"6번"),
Data(R.mipmap.ic_launcher,"7번"),
Data(R.mipmap.ic_launcher,"8번"),
Data(R.mipmap.ic_launcher,"9번"),
Data(R.mipmap.ic_launcher,"10번")
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_custom__recycler_view)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = CustomAdapterRecyclerVIew(dataList)
}
}
class CustomViewHolder(itemView : View, onClick: (position: Int) -> Unit)
: RecyclerView.ViewHolder(itemView) {
val profile: ImageView = itemView.listview_imageview
val name: TextView = itemView.listview_textview
init {
itemView.rootView.setOnClickListener {
onClick(adapterPosition)
}
}
}
class CustomAdapterRecyclerVIew(
private val dataList: ArrayList<Data>
) : RecyclerView.Adapter<CustomViewHolder>() {
override fun getItemCount(): Int = dataList.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false)
return CustomViewHolder(itemView, onClick = { position ->
Toast.makeText(parent.context, dataList[position].name, Toast.LENGTH_SHORT).show()
})
}
override fun onBindViewHolder(holder: CustomViewHolder, position: Int) {
holder.profile.setImageResource(dataList[position].profile)
holder.name.text = dataList[position].name
}
}
구분 | ListView | RecyclerView | ||
Item Layout | 세로 방향만 지원 | 가로, 세로, 사선 방향 모두 지원 | ||
Item Animation | 없음 | 애니메이션을 처리하는 클래스 지원 | ||
Item Decoration | Android:divider 속성을 통해 아이템들을 구분 | RecyclerView.ItemDecoration 객체를 통해 구분선 활용 |
||
Click Detection | ItemView에 대한 AdapterView.OnItemClickListener 등 인터페이스 지원 | 없음 |
*Adapter : 데이터 목록을 Item View로 생성해주는 객체
*ViewHodler : 각 Item View를 보관하는 객체로, Item View의 각 구성 요소를 저장하여 반복적으로 조회하지 않고 즉시 액세스 할 수 있습니다.
*LayoutManager : Item View가 나열되는 형태를 관리
'Android > Android의 모든 것' 카테고리의 다른 글
👋Android의 모든 것 : 1️⃣App Manifest, 2️⃣Context (0) | 2022.03.16 |
---|---|
👋Android의 모든 것 : 1️⃣Android, 2️⃣Android SDK, 3️⃣Platform Architecture (0) | 2022.03.16 |
👋Android의 모든 것 : 1️⃣안드로이드에서 백그라운드 작업(Service, IntentService, JobintentService , WorkManager) (0) | 2022.03.11 |
👋Android의 모든 것 : 1️⃣OkHttp, 2️⃣OkHttp Interceptor (0) | 2022.03.08 |
👋Android의 모든 것 : 1️⃣ViewBinding | DataBinding (0) | 2022.03.05 |