본문 바로가기
Dart/Flutter

[Flutter] Theme.of(context) 성능 이슈

by 검은냥냥이 2023. 5. 10.

Flutter에서 테마 오브(context)를 사용할 때 발생할 수 있는 성능 이슈에 대한 문제점을 알아보겠습니다.

 

중복 빌드

아래의 코드의 경우에는 `builder` 함수가 위젯 트리가 빌드될 때마다 호출되어 여러 번 빌드가 발생됩니다. 위젯 상태의 변경이나 애니메이션, 화면 리사이즈 등 다양한 이벤트가 발생할 때마다 호출됩니다.

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('My App'),
      ),
      body: Builder(
        builder: (BuildContext context) {
          print('build');
          return Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(
                'Hello, world!',
                style: Theme.of(context).textTheme.headline1,
              ),
            ],
          );
        },
      ),
    );
  }
}

 

개선방향

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return Container(
      color: theme.primaryColor,
      child: Text(
        'Hello, world!',
        style: theme.textTheme.headline1,
      ),
    );
  }
}

`BuildContext` 대신 `BuildContextTheme`을 사용하여 테마를 가져옵니다. 이 방법은 테마를 매번 새로 가져오지 않아도 되기 때문에 불필요한 빌드를 줄일 수 있습니다.

 

class MyWidget extends StatefulWidget {
  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  late ThemeData _theme;

  @override
  void initState() {
    super.initState();
    _theme = Theme.of(context);
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: _theme.primaryColor,
      child: Text(
        'Hello, world!',
        style: _theme.textTheme.headline1,
      ),
    );
  }
}

`StatefulWidget`을 사용하여 상태를 관리하고, `initState` 함수 내부에서 테마를 가져온 후 상태를 업데이트합니다. 이 방법은 테마를 한 번만 가져오기 때문에 불필요한 빌드를 줄일 수 있습니다.

 

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  final ThemeData myTheme = ThemeData(
    primaryColor: Colors.blue,
    accentColor: Colors.red,
    textTheme: TextTheme(
      headline1: TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
      bodyText1: TextStyle(fontSize: 16.0),
      button: TextStyle(fontSize: 18.0, color: Colors.white),
    ),
  );

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'My App',
      theme: myTheme,
      home: MyHomePage(),
    );
  }
}

`BuildContext`를 사용하지 않고 메인에 `ThemeData`를 지정하여 사용합니다.

728x90
사업자 정보 표시
레플라 | 홍대기 | 경기도 부천시 부일로 519 화신오피스텔 1404호 | 사업자 등록번호 : 726-04-01977 | TEL : 070-8800-6071 | Mail : support@reafla.co.kr | 통신판매신고번호 : 호 | 사이버몰의 이용약관 바로가기