안녕하세요 🥳 백엔드 개발자 제임스입니다.
오랜만에 글을 작성합니다. 난데없이 '플러터에 대한 내용'으로 인사를 드리네요. 최근에 앱 개발 프로젝트를 진행하고 있습니다. 물론 저는 서버 개발을 담당합니다. 그럼에도 팀이 사용하는 기술에 대해 안다면, 더 좋은 결과를 만들 수 있겠다고 판단하여 이렇게 취미로나마 플러터를 공부하고 있습니다.
오늘 소개할 내용은 List 목록을 출력하는 방법 그리고 성능 개선입니다. 최근에 이 부분을 공부하면서 재미와 흥미를 느껴서 이렇게 기록합니다.
1) ListView
여러 항목을 나열하는 데 사용하는 스크롤 위젯(Widget)입니다. 말 그대로 많은 양의 데이터를 연속적으로 보여줍니다. 예시로 아래와 같이 코드를 작성할 수 있습니다.
예시코드 1.
즉 ListView가 children [] 속성을 가지면서, Column 또는 Row를 지정하지 않고 특정 방향으로 항목을 모두 출력할 수 있습니다.
이러한 ListView는 내부에 Collection for를 통해 개수를 알 수 없는 항목들도 출력할 수 있습니다.
예시코드 2.
body: FutureBuilder(
future: webtoons,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView(
children: [
for (var webtoon in snapshot.data!) Text(webtoon.title),
],
);
}
return const Center(
child: CircularProgressIndicator(),
);
},
),
⬆ FutureBuilder를 통해 API 결과 목록을 갖고 오고 있습니다. 현재 future 타입은 List<Widget>입니다.
해당 결과는 Snapshot에 저장되어 있습니다. 따라서 ListView의 children[] 내부에서 for를 통해 항목 데이터에 접근하고 있습니다.
이처럼 ListView를 통해서 List 타입의 항목을 출력하는 예시를 보았습니다.
항목을 출력하기 위해 매우 유익한 위젯입니다. 하지만 문제는 ListView는 데이터 목록을 한 번에 가져와서 조작합니다.
가령 데이터의 용량이 큰 이미지 거나 양이 무수히 많다면, 메모리가 버티지 못하고 죽고 말 것입니다.
2) ListView.builder
ListView의 문제를 개선하여 동적인 목록을 생성하는 위젯입니다. 즉, 이 위젯은 사용자가 보고 있는 위치(섹션)에 해당하는 데이터만 렌더링 하여 보여줍니다.
이와 같은 기능이 가능한 이유는 인덱스를 활용하기 때문입니다. itemBuilder 함수를 사용하여 각 항목을 생성하고, 인덱스에 따라 항목을 반환합니다. 그리고 스크롤이 발생하면 화면에서 벗어나는 항목은 재사용 대기열로 이동합니다. 화면에 들어온다면, 재사용 대기열에서 항목을 가져옵니다. 이 같은 방식 덕분에 메모리 사용량을 줄이고, 성능이 향상합니다.
예시코드 1.
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
var webtoon = snapshot.data![index];
print('$index, ${webtoon.title}');
return Text(
'$index + ${webtoon.title}',
);
},
);
1) scrollDirection : 스크롤 방향 (ListView에도 있음)
2) itemCount : build 할 item 개수
3) itemBuilder: required 인자, index를 통해 항목 출력
위 결과 이미지를 보면, 화면(섹션)에 해당하는 데이터만 콘솔에 출력되는 것을 볼 수 있습니다.
3) ListView.separated
separated는 ListView.builder보다 더 개선된 위젯입니다. 동적인 목록을 생성한다는 점은 builder와 목적이 같습니다. 하지만 separated는 항목 사이에 구분자를 추가할 수 있는 점에서 차이가 있습니다. 따라서 이를 구현하기 위해 separtorBuilder라는 필수인자가 추가됩니다.
즉, 메모리 성능을 개선하여 출력한 목록에서 UI 디자인까지 개선된 위젯이라고 생각하면 좋습니다.
예시코드 1.
return ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
var webtoon = snapshot.data![index];
return Text(webtoon.title);
},
separatorBuilder: (context, index) => const SizedBox(
width: 20,
),
);
위에서 작성했던 ListView.builder 코드에 명칭을 separated로 변경하고, separatorBuilder로 SizedBox() 위젯을 구분자로 반환하도록 추가했습니다.
'개발 > Dart&Flutter' 카테고리의 다른 글
[Flutter] Android-Cannot fit requested classes in a single dex file 해결 방법 및 원인 분석 (2) | 2024.09.26 |
---|