
플러터에서 길이가 가변하는 여러 항목의 목록을 만들 수 있는 위젯으로 ListView()가 있다. 이 위젯과 함께 흔히 언급되는 위젯으로 ListView.builder()가 있는데, 이 둘의 차이를 알아보고자 한다.
ListView()의 가장 큰 특징은 바로, 자식 위젯들을 한 번에 생성한다는 점이다. 즉, 구현 상으로는 Column()과 큰 차이가 없어보인다. 그래서 ListView()는 고정된 길이의 리스트에 적합하다. 리스트 항목의 개수가 많지 않을 때에도, ListView()를 사용하는 것이 유리하다. 구현은 매우 간단하다. Column() 위젯을 만들 때처럼, children 속성으로 항목 위젯들을 넣어주기만 하면 된다.
ListView(
children: <Widget>[
ListTile(
title: Text('다크 모드'),
trailing: Switch(
value: _isDarkMode,
onChanged: (value) {
setState(() {
_isDarkMode = value;
});
},
),
),
ListTile(
title: Text('알림 설정'),
onTap: () {
// 알림 설정 화면으로 이동
},
),
ListTile(
title: Text('언어 설정'),
onTap: () {
// 언어 설정 화면으로 이동
},
),
],
)
ListView.builder()는 ListView()와는 달리, 화면에 보이는 항목 위젯들과 약간의 여유분만을 생성하고, 나머지는 스크롤에 따라 동적으로 생성하거나 제거한다. 그리하여, 리스트의 길이가 길거나, 동적으로 변하는 경우에 유리하다. 이렇게 성능 상의 이점이 있기 때문에 항목이 많은 경우에도 부드러운 스크롤이 가능하다. 구현은 약간 복잡한데, 속성으로 항목들의 길이가 들어가는 itemCount이 있고, 각 항목을 생성하는 itemBuilder 함수가 있다.
ListView.builder(
itemCount: _items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_items[index].title),
subtitle: Text(_items[index].description),
leading: Image.network(_items[index].imageUrl),
onTap: () {
// 상세 페이지로 이동
},
);
},
)
다시 정리해보면, ListView()는 그 구현이 간단한 대신, 자식 위젯들을 생성 시점에 모두 생성하기 때문에 상대적으로 고정된 길이와 짧은 항목에 유리하며, 성능 상의 이점이 상대적으로 적다. 반면, ListView.builder()는 구현이 어려운 반면, 필요한 항목들만을 동적으로 생성하기 때문에 성능 상의 이점을 가지며, 가변하고 긴 리스트에 유리하다고 할 수 있다.