본문 바로가기
프로그래밍/Flutter

[flutter 상태관리] 3. stateless widget 실습

by 신나요 2022. 6. 1.

지난 포스트에서 stateless widget을 상태의 관점에서 정적 위젯과, 상태가 주입된 위젯으로 분류해 보았습니다. 이번 글의 목표는 정해진 사진을 출력하는 정적 위젯을 만들어보고 정적 위젯을 다시 상태가 주입된 위젯으로 바꾸는 코딩을 해보는 것입니다.  GridView로 갤러리를 만들어보는 데모도 포함되어 있습니다. 기초적인 과정이니 눈으로 가볍게 따라와 주세요. 전체 소스를 참고하고 싶으신 분은 아래로 쭉 내려주세요.

 

이전 글을 읽고 오시면 더욱 좋습니다:)

 

[flutter 상태관리] 2. stateless widget (스테이트리스 위젯)

플러터에서 상태 관리에 관한 포스팅을 하고 있습니다. 아직은 좀 더 작은 주제인 stateless widget과 stateful widget을 사용하는 로컬 상태 관리에 대해 알아보도록 하겠습니다. 이번 포스트는 상태를

nayotutorial.tistory.com

 

이번 포스트는 다음 내용을 다루고 있습니다.

  • 정적 위젯 만들기
  • 갤러리 화면과 상태가 주입된 위젯 만들기

정적 위젯 만들기

아래에 main 함수가 있습니다.

여기에서 클래스를 만드는 것부터 시작하겠습니다.

vscode에서 stless라고 작성하면 나오는 숏컷 메뉴에서 stateless widget을 쉽게 만들 수 있습니다.

숏컷을 통해 클래스를 만들면 아래와 같은 포멧으로 작성됩니다.

소스를 다시 수정해서 Container를 MaterialApp으로 바꿔주었습니다.

title은 'Photo'를 설정하였고, home에는 아직 제공할 위젯이 없으므로 빈 채로 남겨두었습니다. home에 넣어줄 위젯은 정적 이미지를 표시할 아주 간단한 정적 위젯이 될 것입니다.

 Stateless 위젯인 Photo 클래스를 만들어 주었습니다. url이라는 final 필드를 가지고 있고 클래스가 생성되면서 url 주소가 바뀌는 걸 원하지 않기 때문에 사진의 주소를 고정값으로 가지고 있습니다. build 메소드에서는 Image의 network 생성자를 사용해서 Image위젯을 만들고 있습니다. 이미지의 소스는 단순히 고정 url값을 넣어주고 있습니다. 이것으로 정적 위젯의 작성은 끝이 났습니다.

마지막으로 App클래스의 home설정과 main 함수의 호출부분을 수정하겠습니다.

MaterialApp의 home에 방금 만든 Photo 위젯을 넣어주었습니다. 그리고 main 함수에서는 runApp을 호출하고 애플리케이션의 위젯을 전달하면 앱을 구동할 준비가 완료되었습니다.

에뮬레이터를 화면을 살펴보면 아래와 같습니다.

귀여운 퍼그 사진이 화면에 나타나고 있습니다. 단순 정적 위젯 하나가 화면에 그려져서 나타나는 결과입니다. 정적 위젯이므로 화면이 갱신되거나 하는 일은 존재하지 않습니다. 정적 위젯을 만들어 봤으니 상태가 주입된 위젯을 만들어 보도록 하겠습니다.

 

이제 남은 목표는 아주 간단한 사진 갤러리를 만드는 것입니다. 그리고 갤러리를 만들면서 상태가 주입된 위젯을 만들어보도록 하겠습니다.


갤러리 화면과 상태가 주입된 위젯 만들기

이제 여러 이미지를 보여주는 갤러리 페이지를 만들어 보도록 하겠습니다. 먼저 갤러리에서 보여줄 사진의 URL을 가지는 변수를 추가하겠습니다.

pixabay.com에 올라와있는 무료 사진의 url을 저장하는 urls를 선언하였습니다.

이제 MaterialApp 위젯 내부에서 단일 Photo 위젯을 렌더링 하는 대신 갤러리 위젯을 추가하도록 하겠습니다.

Gallery는 위젯에 상태를 주입할 것이고, 여기서 상태는 final 문자열 값입니다. 그리고 결과적으로 갤러리의 제목으로 설정됩니다. urls역시 위젯에 주입되는 상태입니다. 생성자 Gallery()를 보면 title과 urls를 필수 매개변수로 설정하였습니다. build메서드에서는 주입된 상태를 데이터로 Scaffold위젯을 반환하고, 스캐폴드의 appBar에서는 정적 Text위젯으로 title을 설정하였으며 title프로퍼티 값을 기반으로 화면에 출력됩니다.

스캐폴드의 body를 살펴보면 body성을 GridView로 설정하고 있습니다. 이 GridView를 이용해 사진 갤러리를 표시 할 수 있습니다. GridView의 count 생성자로 그리드 뷰 위젯을 생성하고 있습니다. crossAxisCount가 2로 설정하고 있으므로 한 줄에 두 개의 이미지 표현을 하게 됩니다.

children 속성은 List.of로 배열을 만들어 속성을 채우고 있습니다. 생성자에서 받은 URL을 매핑하면서 해당 url을 하나씩 가져와서 url 맵을 Photo위젯으로 반환하게 됩니다.

 

Photo 클래스에서 Gallery위젯에서 사용하기위해서 url은 고정 문자열로 돼있었는데 이제 생성자에서 상태를 주입하도록 바꿔주어야 합니다.

url을 고정값으로 초기화하는 대신 생성자에서 건네받은 값으로 초기화되도록 수정하였습니다.

이제 App클래스의 build를 수정하면 끝입니다.

home 속성에 Gallery 위젯 다시 말해 상태가 주입된 위젯을 설정해 주었고, title과 urls를 상태들을 건네주고 있습니다.

아래가 완성된 화면입니다.

각 Photo 위젯이 깔끔하게 배치되고 있지는 않지만, 갤러리의 역할은 충분히 해내고 있는 것 같습니다. 우리가 해본 일을 다시 생각해보면 처음엔 정적 위젯인 Photo 위젯을 만들었고, Photo위젯을 다시 상태가 주입된 위젯 즉 생성자에서 데이터를 건네받는 위젯으로 만들어 갤러리 화면을 완성했습니다.

 

전체소스

import 'package:flutter/material.dart';

void main() {
  runApp(const App());
}

const List<String> urls = [
  "https://cdn.pixabay.com/photo/2017/06/29/13/29/pug-2454270_1280.jpg",
  "https://cdn.pixabay.com/photo/2014/09/19/21/47/chihuahua-453063_1280.jpg",
  "https://cdn.pixabay.com/photo/2015/06/15/23/56/chihuahua-810789_1280.jpg"
];

class App extends StatelessWidget {
  const App({ Key? key }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Photo',
      home: Gallery(title:'Gallery', urls: urls,)
    );
  }
}

class Gallery extends StatelessWidget {
  final String title;
  final List<String> urls;

  const Gallery({required this.title, required this.urls });

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: GridView.count(
        crossAxisCount: 2,
        mainAxisSpacing: 5.0,
        crossAxisSpacing: 5.0,
        padding: const EdgeInsets.all(5.0),
        children: List.of(urls.map((url)=> Photo(url: url)),
      )
    ));
  }
}

class Photo extends StatelessWidget {
  final String url;

  const Photo({required this.url});

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Image.network(url),
    );
  }
}

여기까지 수고하셨습니다.

stateless widget이 끝났으니 다음 포스트에서는 stateful widget이야기를 할 차례가 됐습니다.

stateful widget이야기를 하면서 오늘 만든 갤러리 화면에 태그로 필터링하는 기능을 추가해 보도록 하겠습니다.

댓글