Things take time

[Flutter] Route에서 화면 종료 시, 데이터 전달 본문

Flutter

[Flutter] Route에서 화면 종료 시, 데이터 전달

겸손할 겸 2020. 7. 16. 13:59

[데이터 전달]

이전 포스팅에서는 루트간 데이터 전달에서, 데이터를 보내는 것을 알아봤고 이번에는 루트를 연 루트에서 데이터를 받아올때를 처리하겠다. Android의 startActivityForResult와 iOS의 딜리게이트 패턴과 같은 것으로 생각하면 되겠다.

 

https://flutter-ko.dev/docs/cookbook/navigation/returning-data

 

이전 화면에 데이터 반환하기

새로운 화면으로부터 이전 화면으로 데이터를 반환해야하는 경우가 있습니다. 예를 들어,사용자에게 두 가지 옵션을 보여주는 화면이 있다고 합시다. 사용자가 한 옵션을 선택했을 때그것을 첫

flutter-ko.dev

공식문서만큼 설명이 잘 된 것은 없으므로 참고하자.

 

다만 공식문서에서는 Navigator.push를 통해 직접 루트를 명시해서 열었으나, 이전 포스팅에서 말한 것 처럼 유연한 방식으로 나는 화면전환할 때, namedPush를 사용하도록 하겠다.

 

A루트에서 B루트를 연다고 가정한다. 여기서 B루트의 이름은 루트 테이블에 아래와 같이 등록되어있다.

      routes: {
        "/": (context) => MainField(),
        "/map": (context) => LetsEatMap(),
        "/mapInfo": (context) => LetsEatMapInfo(),
      },

자 그럼 A루트에서 버튼에 아래와 같은 클릭 이벤트를 걸면 A->B루트(/mapInfo 로 등록된 루트, 위에서 LetsEatMapInfo())로 이동된다.

  void _navigateMapInfo(Place place) async {
    final result =
        await Navigator.pushNamed(context, '/mapInfo', arguments: place);
    if(result == null){
      print('result is null');
    }else{
      print(result.toString());
    }
  }

async라는 상수명을 함수 뒤에 쓰면, 비동기를 뜻한다.

즉, 이 함수는 비동기적으로 돌기시작하고 비동기의 작업은 await 상수가 적힌 줄이다.

result란 상수 값은 pushNamed를통해 B루트를 열고 B루트가 값을 리턴해줄때 까지 기다리게 된다.

 

그리고 result의 값을 체크하여 이후 작업을 수행한다.

B루트에서 2개의 버튼을 넣고, 각각에 아래와 같은 소스를 작성했다.

          Container(
            color: Colors.redAccent,
            height: 44,
            width: double.infinity,
            padding: EdgeInsets.only(left: 20, right: 20),
            child: Row(
              children: <Widget>[
                InkWell(
                  child: Icon(
                    Icons.arrow_back_ios,
                    color: Colors.white,
                  ),
                  onTap: () {
                    print('tab');
                    Navigator.pop(context, null);
                  },
                ),
                Expanded(
                  child: InkWell(
                    child: Align(
                      alignment: Alignment.centerRight,
                      child: Text(
                        '선택',
                        style: TextStyle(color: Colors.white, fontSize: 18),
                      ),
                    ),
                    onTap: (){
                      Navigator.pop(context, '값을 리턴했어요.');
                    },
                  ),
                )
              ],
            ),
          )

앱바처럼 상단을 만들었다.

상단의 <아이콘을 누르면 Navigator.pop(context, null)로 null값을 리턴하고, 선택이란 텍스트를 클릭하면 '값을 리턴했어요'라는 String 값을 리턴하며 화면을 종료한다.

 

그리고 각각의 위젯을 클릭하면, print문에 의해 'return is null'이란 값 혹은 '값을 리턴했어요'라는 값이 로그에 찍히게 된다.

 

 

[더 간단하게]

 

위와 같은 소스이지만, 아래처럼 소스를 작성해도 된다. Navigator.pushNamed라는 함수 자체가 Future라는 객체를 반환하는 함수이기 때문에 async를 받아서, await를 하지 않고 아래처럼 해도 된다.

    Navigator.pushNamed(context, '/mapInfo', arguments: place).then((value) {
      print("then!! : $value");
    });