Flutter와 Firebase로 Android iOS 둘 다 만들기 3 리스트 출력하기

3 분 소요

앱에서 자주 쓰이는 리스트 출력을 알아봅니다.

참고 정보

공식홈의 리스트를 학습하면 좋습니다.

참고: https://flutter-ko.dev/docs/cookbook#lists

다만 공식홈에서 데이터를 다루는 것에 대한 설명이 없어서 간단히 데이터를 넣어 시험해봅니다.

List

결국 배열입니다.

자스(javascript)에 비해 조금 귀찮은 구석이 있지만, 다른 언어에 비하면 편리한 수준입니다.

자스처럼 아무거나 막 넣을 수 없고 대부분의 컴파일 언어들 처럼 형을 지정해야합니다.

초기화

List<String> items = []

이제 문자열로 이루어진 배열 데이터를 다룰 수 있습니다.

추가

items.add('a');
items.add('b');

이제 items의 길이는 2개가 되었습니다.

삭제

items.removeLast();

items의 마지막 원소가 제거 되었습니다.(그 밖에도 첫번째 원소를 제거하든, 특정 원소를 제거하든 다양한 메쏘드가 있겠죠?)

데이터와 표시부

사실 뻔해서 도큐를 안보고도 느낌으로 알 수 있는 것들입니다.

하지만 어디서부터 해야할 지 감이 안잡힙니다.

버튼 이벤트에서나 print해서는 감이 안옵니다.

시각적으로 표현해야 명확한 이해를 할 수 있습니다.

그래서 화면에 표현해보면 명확해집니다.

Widget body(BuildContext context) {
  return Container(
    padding: EdgeInsets.all(20),
    child: testList()
  );
}
Widget testList () {
  // 데이터 가공
  List<String> items = [];
  items.add('aaa');
  items.add('bbb');    
  items.add('ccc');    
  items.add('ddd');    
  items.add('eee');    
  items.removeLast();

  // 렌더링
  return Center(
    child: Text(items[2])
  ); 
}

이제 바디에서 새로운 위젯을 렌더링 해봅니다.

센터에 ccc가 잘 표시 되는 것을 볼 수 있습니다.

결국 데이터 가공하는 부분과 표시(렌더링)하는 부분을 놓고 생각하면 편합니다.

한꺼번에 표시하기

사실 어떤 한 요소가 아닌 일괄로 렌더링을 하는 것이 많이 사용합니다.

그럴 때 List의 generate를 사용하면 됩니다~

Widget testList () {
  List<String> items = [];
  items.add('aaa');
  // ..
  return Column(
    children: List.generate(items.length, (index) {
      return Text(items[index]);
    })
  );
}

alt col iter

vue를 배우고 오신분들은 data와 v-for의 느낌이란 것을 알 수 있습니다~

한꺼번에 넣기

반복문은 대부분의 언어가 그렇든 for를 사용합니다.

Widget testList () {
  List<String> items = [];
  for (var i = 0; i < 10; i++) items.add('a $i')
  return Column(
    children: List.generate(items.length, (index) {
      return Text(items[index]);
    })
  );
}

alt for

for문으로 10개의 제한을 두고 $를 사용해서 문자열과 숫자를 표시했습니다.

자스에서는 템플릿 스트링(${value}) 같은 것인데 찍었는 데 맞췄습니다..

dart에 조금 익숙해지면 이런 식으로 초기에 바로 넣을 수도 있습니다.

Widget testList () {
  List<String> items = List.generate(10, (i) => 'aa $i');
  return Column(
    children: List.generate(items.length, (index) {
      return Text(items[index]);
    })
  );
}

물론 전 별로 좋아하지 않습니다. 저처럼 여러가지 플랫폼을 다루는 경우 몇 줄 줄이는 효과 는 좋지만 가독성에 방해가 됩니다.

화면 표시의 문제점

지난번 배운 레이아웃의 개념으로는 에러가 나는 상황이 있습니다.

화면 크기보다 양이 많으면 문제인 것입니다.

Widget testList () {
  List<String> items = List.generate(100, (i) => 'aa2 $i');
  return Column(
    children: List.generate(items.length, (index) {
      return Text(items[index]);
    })
  );
}

alt error

100개를 표현할 경우 바로 이렇게 에러(하단부)가 나버립니다.

스크롤이 필요한 상황입니다.

그래서 우리는 ListView 같은 것으로 표시해야 하는 것입니다.

Listview

리스트뷰는 위처럼 대입의 느낌으로 보면 안되고 만들어주는 느낌? 으로 접근해야합니다.

Widget testList () {
  List<String> items = List.generate(100, (i) => 'aa2 $i');
  return ListView.builder(
    itemCount: items.length,
    itemBuilder: (context, i) {
      return Text(items[i]);
    },
  );
}

alt list builder

이제 스크롤이 생겨서 에러 없이 100개의 아이템을 모두 볼수 있습니다.

만들어야하기 때문에 .builder로 호출해서 몇개를 표시할지, 어떻게 표시할지 정해야합니다.

코드에서 중요한 요소는 바로 context입니다.

화면의 주인?이 필요하기 때문입니다.

ListTile

리스트뷰에는 텍스트 위젯 보다는 타일이 어울립니다.

Widget testList () {
  List<String> items = List.generate(100, (i) => '리스트 테스트 $i');
  return ListView.builder(
    itemCount: items.length,
    itemBuilder: (context, i) {
      return ListTile(
        title: Text(items[i]),
        subtitle: Text('this is test $i ㅎㅎㅎㅎㅎㅎ')
      );
    },
  );
}

alt listtile

이제 좀 볼만해졌죠?

느끼는 부분

플러터를 할 때마다 반가운 느낌은 vue & vuetify와 비슷한 느낌이기 때문입니다.

<template>
  <v-list-item v-for="(item, i) in items" :key="i">
    <v-list-item-title v-text="item"/>
    <v-list-item-subtitle>
      {{ `this is test ${i} ㅎㅎㅎㅎㅎㅎ` }}
    </v-list-item-subtitle>
  </v-list-item>
</template>
<script>
export defaut {
  data () {
    return {
      items: []
    }
  },
  mounted () {
    for (let i = 0; i < 100; i++) items.push(`리스트 테스트 ${i}` )
  }
}
</script>

만약 뷰로 위의 코드와 동일한 화면을 나타낸다면 이런 코딩을 해주면 됩니다.

플러터의 구성과 비슷한 느낌이 들지 않나요?

최근의 트렌드가 화면과 데이터를 공유하는 식들(mvc, mvvm 등등)이기 때문에 익숙해서 생산성이 좋은 것이죠~

소스코드

https://github.com/fkkmemi/ff

영상

댓글남기기