Flutter - Widget의 build메서드와 BuildContext

로건·2022년 7월 11일
1

Flutter

목록 보기
2/3

StatelessWidget이나 StatefulWidget의 State든 생성을 할 때 Widget을 리턴하는 build 메서드를 가진며 BuildContext 타입의 인자를 하나 받습니다. 이들의 역할을 무엇일까요?


build 메서드와 BuildContext 타입

override메서드인 build 메서드는 구현한 UI 위젯들을 화면에 출력될 수 있도록 리턴해줍니다.

그렇다면 이 메서드에서 인수로 받는 BuildContext타입의 context는 무엇일지?
BuildContext 타입은 현재 위젯의 위젯트리상에서 위치에 관한 정보를 담고 있습니다.
context는 어떤 위젯의 정보를 담고있을까? 바로 return 하는 위젯의 부모 위젯에 대한 위치 정보를 가지고 있습니다.

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

  
	// 여기서 context는 이 MyHomePage를 부르는 부모위젯의 위치정보를 담고 있음
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar( title: Text("MyHomePage"), ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text('Test', ),
          ],
        ),
      ),
    );
  }
}



Context를 다루면서 자주하는 실수

of 함수를 다룰 때

현재 위젯과 가장 가까운 어떠한 위젯을 찾을때 보통 of 함수를 많이 사용합니다.

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

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar( title: Text("MyHomePage"), ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: (){
                Scaffold.of(context).showSnackBar(SnackBar(content: Text('snack bar')));
              },
              child: Text('button'),
            ),
          ],
        ),
      ),
    );
  }
}

이때, 위 코드에서 Scaffold.of 함수는 인자로 제공해준 context에서 조상 중 가장 가까운 Scaffold를 반환해주는 역할을 합니다. 하지만 위에서 말했듯 저 context 부모의 위치가 담긴 BuilContext입니다. 즉, 현재 Scaffold보다 부모에 존재하는 Scaffold를 찾게되는 것입니다.

이를 해결하기 위해선 두가지의 방법이 존재합니다. Builder를 이용하는 방법새로운 widget class를 만들어 주는 방법.

Builder 이용하여 Scaffold 아래에 새로운 context를 생성시키기

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

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar( title: Text("MyHomePage"), ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Builder(builder: (ctx) {
              return ElevatedButton(
                onPressed: (){
                  Scaffold.of(ctx).showSnackBar(SnackBar(content: Text('snack bar')));
                },
                child: Text('button'),
              );
            })
          ],
        ),
      ),
    );
  }
}



새로운 widget class으로 만들어주기

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

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar( title: Text("MyHomePage"), ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            MyButton(),
          ],
        ),
      ),
    );
  }
}

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

  
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: (){
        Scaffold.of(context).showSnackBar(SnackBar(content: Text('snack bar')));
      },
      child: Text('button'),
    );
  }
}

Builder 클래스는 내부 위젯들을 새로운 위젯으로 강제적으로 만들며 그 부모(여기선 Scaffold)의 context로 접근가능하게 만들어줍니다. 하지만 새로운 Widget class를 구현하는 것은 재사용성 측면에서 매우 뛰어날뿐만 아니라 가독성과 깔끔함까지 같이 가져갈 수 있습니다.

감사합니다😁

profile
Life Designer

0개의 댓글