안녕하세요. 중곰입니다.
안드로이드 UI 의 진화 ListView에서 RecyclerView, 그리고 Compose까지에서
Part.1 ListView 입니다.
개발 연차가 되어가지만 한번씩 내용을 정리하면서
글을 쓰기 위해서 정리해보았습니다.
안드로이드에서 UI 중 리스트 데이터를 보이기 위해 일반적으로 사용되는 UI는
ListView, RecyclerView, Compose(LazyColum)이 있습니다.
가장 먼저 ListView를 살펴봅니다.
ListView
- 기본 제공되는 위젯 중 하나이며, 세로로 스크롤 가능한 화면을 표시할 때 사용
- 리스트의 각 항목은 일반적으로 단일 뷰 (ex : TextView, ImageView) 또는 커스텀 뷰로 구성
특징
- 리스트 데이터를 화면에 표시하기 위한 간단한 방법
- 어댑터 : 데이터와 뷰를 연결하는데 ArrayAdapter or CursorAdapter 주로 사용
- 적은양의 데이터나 정적 리스트에 적합
언제 사용
- 간단한 리스트가 필요할 때
- 데이터 항목이 적고, 스크롤 성능이 중요하지 않을 때
- 간단한 어댑터를 사용해 빠르게 구현해야 할 때
간단한 예제
/** xml **/
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
/** MainActivity **/
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val listView = findViewById<ListView>(R.id.listView)
val data = arrayOf("Item 1", "Item 2", "Item 3")
val adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, data)
listView.adapter = adapter
}
}
한계점
- 뷰 재사용 문제
- RecyclerView 처럼 효율적인 뷰 재사용을 제공하지 않음
- 사용자 정의 ViewHolder를 구현해야만 재사용 최적화가 가능
- 레이아웃 제한
- 가로 방향 스크롤 및 Grid 레이아웃을 지원하지 않음
- 기본적으로 세로 반향의 단일 열 레이아웃만 지원
- 가로 방향 스크롤 및 Grid 레이아웃을 지원하지 않음
- 애니메이션 부족
- 스크롤 애니메이션과 UI 업데이트가 제한적
- 성능 저하
- 대량의 데이터를 처리할 때 성능 문제가 발생
- 스크롤 시 findViewById 호출이 빈번하여 비용이 증가
- findViewById는 뷰를 계층 구조에서 검색하므로 호출 비용이 큼
- 확장성 부족
- 다양한 레이아웃 매니저(Linear, Grid, Staggerd 등)를 지원하지 않음
- Item Decoration( 아이템 구분선) 과 같은 기능 제한적
ListView 성능 개선 방안
- ViewHolder 패턴 구현
- findVidwById 호출을 최소화하기 위해 ViewHolder 패턴을 사용해 각 뷰의 참조를 캐싱
- 예제
class MyAdapter(context: Context, private val data: List<String>) : BaseAdapter() { private val inflater: LayoutInflater = LayoutInflater.from(context) override fun getCount(): Int = data.size override fun getItem(position: Int): Any = data[position] override fun getItemId(position: Int): Long = position.toLong() override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View { val viewHolder: ViewHolder val view: View if (convertView == null) { view = inflater.inflate(android.R.layout.simple_list_item_1, parent, false) viewHolder = ViewHolder(view.findViewById(android.R.id.text1)) view.tag = viewHolder } else { view = convertView viewHolder = view.tag as ViewHolder } viewHolder.textView.text = data[position] return view } class ViewHolder(val textView: TextView) }
- RecyclerView로 전환
- ViewHolder 패턴을 내장하고 있어 개발자가 직접 구현하지 않아도 성능 최적화가 이루어짐
ListView 대안
- RecyclerView
- 가장 직접적인 대안
- 주요 장점
- 효율적인 뷰 재사용 (ViewHolder 패턴 내장)
- 다양한 레이아웃 지원(LinearLayoutManager, GridLayoutManager)
- 커스텀 애니메이션, 드래그 앤 드롭, 아이템 삽입/삭제 애니메이션 지원
- ScrollView + LinearLayout
- 데이터가 매우 적고 정적인 경우, ScrollView와 LinearLayout을 사용해 수동으로 리스트 구현 가능
- 데이터 많을 경우 비효율적
- Jetpack Compose (LazyColumn)
- 선언형 UI 방식으로 ListView와 RecyclerView를 대체
- 주요 장점
- 적은 코드로 구현 가능
- 변경된 상태만 기반으로 필요한 UI를 재구성하므로, 업데이트 성능 최적화
- 재사용 및 업데이트 처리 비교
- ListView
- 기본적으로 전체 리스트를 다시 그리는 방식 (invalidate)으로 UI 업데이트
- ViewHolder 패턴을 구현하지 않으면, 모든 뷰가 새로 생성되어 성능 저하
- RecyclerView
- ViewHolder 패턴으로 기존 뷰를 재사용하여 효율적 업데이트
- notifyItemChanged 같은 메서드를 명시적으로 호출해야 하며, 뷰를 갱신하려면 데이터를 수동으로 바인딩
- Compose
- UI 요소는 기존 뷰를 재사용하는 대신 필요한 부분만 다시 그리며, 선언적으로 상태를 관리
- LazyColumn 은 내부적으로 각 리스트 아이템을 상태 기반으로 트래킹하여 변경된 항목만 재구성
- 개발자가 뷰 재사용을 명시적으로 관리하지 않아도, Compose의 상태 관리 메커니즘이 자동으로 처리
- ListView
- 비교항목 ListView vs RecyclerView vs Jetpack Compose
UI 업데이트 방식 전체 다시 그림 재사용(ViewHolder) 후 부분 갱신 변경된 상태만 재구성 재사용 방식 없음(ViewHolder 직접 구현 필요) ViewHolder 기반 상태 기반 트래킹 (뷰 재사용 불필요) 부분 업데이트 관리 복잡 (전체 갱신이 일반적) notifyItemChanged 등 명시적 호출 필요 상태 변화 시 자동 업데이트 애니메이션 처리 직접 구현 필요 ItemAnimator 설정 필요 애니메이션 및 상태 변화가 자연스럽게 통합 개발 복잡성 높은 유지보수 비용 상대적으로 더 구조화된 코드 선언형 방식으로 간소화된 코드
ListView를 살펴보면, 거의 기본 동작에 정적이 데이터와 짧은 데이터를 표기 하기 위한 위젯으로 봐도 될 것 같고, 리스트 데이터를 화면에 처리 하기에는 다소 어려움이 있기에 RecyclerView가 ListView에 가장 적합한 대안이 될 수 있다라고 생각합니다.
마지막 비교항목에서
다음 파트들의 스포가 된것 같지만,
해당 내용이 계속 중복이 되면서
정리해서 비교해보면 좋을 것 같습니다.
그럼 Part.2 RecyclerView에서 다시 만나 뵙겠습니다.
글을 읽어주셔서 감사합니다.
반응형
'Android' 카테고리의 다른 글
안드로이드 UI의 진화: ListView에서 RecyclerView, 그리고 Compose 까지 [Part.3 LazyColumn] (1) | 2025.02.04 |
---|---|
안드로이드 UI의 진화: ListView에서 RecyclerView, 그리고 Compose 까지 [Part.2 RecyclerView] (6) | 2025.01.21 |
Android UI Automator & Espresso 기반 UI 테스트 (3) | 2024.12.24 |
Android Context 정리 (2) | 2024.12.08 |
[Android] Dialog Dim 효과 처리 방법 (0) | 2024.11.29 |