본문 바로가기
Flutter/Flutter 필수개념

[Flutter] BuildContext 와 of 함수

by 붕어사랑 티스토리 2021. 12. 14.
반응형

https://api.flutter.dev/flutter/material/Scaffold/of.html

 

of method - Scaffold class - material library - Dart API

ScaffoldState of(BuildContext context ) Finds the ScaffoldState from the closest instance of this class that encloses the given context. If no instance of this class encloses the given context, will cause an assert in debug mode, and throw an exception in

api.flutter.dev

https://api.flutter.dev/flutter/widgets/BuildContext-class.html

 

BuildContext class - widgets library - Dart API

A handle to the location of a widget in the widget tree. This class presents a set of methods that can be used from StatelessWidget.build methods and from methods on State objects. BuildContext objects are passed to WidgetBuilder functions (such as Statele

api.flutter.dev

 

1. BuildContext

플러터를 하다보면 context라는 인자를 아주 많이 접하게 된다.

 

이 context라는놈은 무엇인가

 

공식문서에서는 다음과 같이 정의되어 있다

 

A handle to the location of a widget in the widget tree.

 

현재 위젯의 위젯트리상의 위치에 관한 정보를 담고있는 변수라는 뜻이다.

 

 

 

 

 

2. Of 함수

플러터를 하다보면 of라는 함수를 많이 접하게 되고 인자로 context를 받는다.

 

of함수는 현재 위젯의 위쪽 방향으로 가장 가까운 위젯을 찾는 함수이다.

 

예를 들어 Scaffold.of(context) 라고 하면

 

현재 context 기준에서 위젯트리 위쪽 방향으로 가장 가까운 Scaffold를 찾아라! 이다.

 

 

3. Of 함수를 쓸 때 주의할점

 

아래와 같은 코드는 에러가 난다.

 

이유는 간단하다. 

 

Scaffold.of(context)로 가장 가까운 Scaffold를 찾으려 하는데 Scaffold와 같은 Build함수에 있어 같은 BuildContext를 공유한다.

허나 아래 코드에서는 Scaffold위로 더이상의 Scaffold가 없기때문에 에러가 난다.

 

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

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

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: _title,
      home: MyStatelessWidget(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Demo')),
      body: Center(
        child: ElevatedButton(
          child: const Text('SHOW BOTTOM SHEET'),
          onPressed: () {
            Scaffold.of(context).showBottomSheet<void>(
              (BuildContext context) {
                return Container(
                  alignment: Alignment.center,
                  height: 200,
                  color: Colors.amber,
                  child: Center(
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: <Widget>[
                        const Text('BottomSheet'),
                        ElevatedButton(
                          child: const Text('Close BottomSheet'),
                          onPressed: () {
                            Navigator.pop(context);
                          },
                        )
                      ],
                    ),
                  ),
                );
              },
            );
          },
        ),
      ),
    );
  }
}

 

그림으로 나타내면 아래와 같은 상황이다

 

반응형

 

이는 아래와 같이 Builder 함수를 통해 중간에 끊어주어 새로운 context를 만들어주면 해결 가능하다

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

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

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: _title,
      home: MyStatelessWidget(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Demo')),
      body: Builder(
        // Create an inner BuildContext so that the onPressed methods
        // can refer to the Scaffold with Scaffold.of().
        builder: (BuildContext context) {
          return Center(
            child: ElevatedButton(
              child: const Text('SHOW BOTTOM SHEET'),
              onPressed: () {
                Scaffold.of(context).showBottomSheet<void>(
                  (BuildContext context) {
                    return Container(
                      alignment: Alignment.center,
                      height: 200,
                      color: Colors.amber,
                      child: Center(
                        child: Column(
                          mainAxisSize: MainAxisSize.min,
                          children: <Widget>[
                            const Text('BottomSheet'),
                            ElevatedButton(
                              child: const Text('Close BottomSheet'),
                              onPressed: () {
                                Navigator.pop(context);
                              },
                            )
                          ],
                        ),
                      ),
                    );
                  },
                );
              },
            ),
          );
        },
      ),
    );
  }
}

 

그림으로 나타내면 아래와 같다.

 

 

 

4. 다른 방법

of 함수는 cost가 많이 드는 함수라고 한다. 좀더 현명한 방법은 scaffold의 global key를 이용하는 것이다.

반응형

'Flutter > Flutter 필수개념' 카테고리의 다른 글

[Flutter] Sliver app bar 배우기  (0) 2021.12.21
[Flutter] Inherited Widget 배우기  (3) 2021.12.16
[Flutter] Matrix4 이해하기  (0) 2021.12.15
[Flutter] state 관리와 provider  (0) 2021.12.14
[Flutter] Animation 이해하기  (0) 2021.11.26

댓글