새로운 강의는 이제 https://memi.dev 에서 진행합니다.
memi가 Vue & Firebase로 직접 만든 새로운 사이트를 소개합니다.

바로가기


Flutter와 Firebase로 Android iOS 둘 다 만들기 5 화면 전환 해보기

2 분 소요

Stateful widget을 사용해서 상태값에 따라 다른 화면을 렌더링해봅니다.

개요

나중에 로그인 절차를 넣으려면 3가지 화면이 필요합니다.

  • 로그인 페이지
  • 로딩(로그인중)
  • 로그인 된 페이지

이 3가지 화면을 상태에 따라 전환 시켜보겠습니다.

클래스 생성

상태를 관리할 모델이 필요합니다.

전역변수 같은 느낌으로 생각하면 됩니다.

class AppState {
  bool loading;
  String user;
  AppState(this.loading, this.user);
}

이것은 자료형이며 아직 실체가 없는 것입니다.

loading은 true/false로 상태를 표시할 것이고

user의 경우 비어있는지 있는지 판단으로 로그인/아웃 상태를 표시할 것입니다.

나중에 user는 fireauth형으로 바뀌게 될 것입니다.

클래스는 매우 복잡하지만.. 모델 역할의 클래스는 여기까지만 알면 됩니다.

같은 글자(AppState, loading등)가 왜이리 반복되는 건지… 작성하면서도 답답합니다..

인스턴스 생성

// var app = AppState(true, '');  
// final AppState app = AppState(true, '');  
final app = AppState(true, '');  

final은 한번만 설정 가능한 변수 입니다.

대입될 형(AppState)이 이미 지정되어있어서 형은 빼도 됩니다.

이런 융통성은 부분은 최근 언어들 특징이기도 합니다.

loading은 true로 user는 비워서(‘’) 시작하게 되는 것입니다.

delay 함수 제작

로딩이 될 상황을 시뮬레이션해보기 위해 만들어봅니다.

_delay () {
  Future.delayed(Duration(seconds: 1), () {
    setState(() => app.loading = false);
  });  
}

갑자기 Future라는 이상한 단어가 나와서 혼란스럽지만..

지금은 그저 1초 지연시키기 위한 방법 정도로만 생각해 두시면 됩니다.

어짜피 나중에 모든 비동기 처리에서 자주 보게될 Future입니다.

loading이 true로 시작됬지만 1초 후에는 false가 되게 해주는 것입니다.

참고: https://api.flutter.dev/flutter/dart-async/Future/Future.delayed.html

State 클래스의 시작부

바로 initState라는 곳입니다.

class _HomeWidgetState extends State<HomeWidget> {
  final app = AppState(true, '');  
  @override
  void initState() { 
    super.initState();    
    _delay();
  }
  _delay () {
    Future.delayed(Duration(seconds: 1), () {
      setState(() => app.loading = false);
    });  
  }
  // ..

State 클래스가 생성될 때 initState()를 들리게 됩니다.

상황별 렌더링

@override
Widget build(BuildContext context) {
  if (app.loading) return _loading();
  if (app.user.isEmpty) return _signIn();
  return _main();
}

이렇게 한번 표시해봤습니다.

  • app.loading일 경우 _loading()을 렌더링하며 밑으로 내려가지 않습니다.
  • app.user가 비었으면 _signIn()을 렌더링합니다.
  • 이상 없는 경우 _main()를 렌더링합니다.

저는 else 보다는 코드 가독성을 위해 상단에서 컷트하는 방식을 사용합니다. 취향일 뿐이니 본인 스타일에 맞게 사용하시면 됩니다.

페이지들 구성

_loading

Widget _loading () {
  return Scaffold(
    appBar: AppBar(title: Text('loading...')),
    body: Center(child: CircularProgressIndicator())
  );
}

가운데 빙글빙글 도는 프로그레스바를 만들었습니다.

_signIn

Widget _signIn () {
  return Scaffold(
    appBar: AppBar(
      title: Text('login page')
    ),
    body: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          Text('id'), Text('pass'),            
          RaisedButton(
            child: Text('login'), 
            onPressed: () {
              setState(() {
                app.loading = true;
                app.user = 'my name';
                _delay();
              });
            }
          )
        ],
      )
    )    
  );
}

가운데 id, pass, login 버튼을 배치했습니다.

로그인 버튼을 누를 때 setState()로 app에 값을 변경하고 _delay()를 호출해서 동작을 확인합니다.

_main

Widget _main () {
  return Scaffold(
    appBar: AppBar(
      title: Text(app.user),
      actions: <Widget>[
        IconButton(
          icon: Icon(Icons.account_circle),
          onPressed: () {
            setState(() {
              app.user = '';
              app.loading = true;
              _delay();
            });
          },
        )
      ],
    ),
    body: Center(child: Text('contents'))
  );
}

appBar 상단에 로그아웃 버튼을 만들어서 동작을 확인합니다.

동작 확인

alt play

소스코드

https://github.com/fkkmemi/ff

영상

댓글남기기