Menu
CoddyTech

initState에서 한 번만 가져오기

Coddy Flutter 여정의 데이터와 네트워크 섹션에 포함된 레슨. 27개 중 7번째.

Flutter는 화면이 다시 그려질 때마다 build를 다시 호출합니다. 각 setState 이후, 휴대전화가 회전할 때, 부모 위젯이 변경될 때도 마찬가지입니다. 초당 여러 번 호출될 수도 있습니다. build는 화면을 설명하기만 해야 하며, 작업을 시작해서는 안 됩니다.

따라서 build 안에 작성한 fetch는 화면이 다시 그려질 때마다 다시 실행됩니다. 실행할 때마다 서버에 새로운 요청을 보내므로, 아무도 답을 요청하지 않았는데도 화면에 다른 답변이 표시될 수 있습니다.

// 다시 그릴 때마다 새로운 요청
FutureBuilder<String>(
  future: fetch('/tip'),
  ...
)

화면이 열릴 때 initState에서 future를 한 번 만들고, 매번 FutureBuilder에 같은 future를 전달하세요.

late Future<String> _tip;

@override
void initState() {
  super.initState();
  _tip = fetch('/tip');
}

initState는 첫 번째 build 전에 한 번 실행됩니다. Flutter의 요청대로 super.initState();로 시작하세요.

challenge icon

챌린지

중급

상단 표시줄의 하트를 누르세요. 팁이 바뀝니다. fetch가 build 안에 있기 때문입니다. 팁을 한 번만 불러오세요:

  • 상태에 late Future<String> _tip;을 추가하세요
  • initState에서 fetch('/tip')으로 값을 설정하세요
  • FutureBuilder에 _tip을 전달하세요

직접 해보기

import 'package:flutter/material.dart';

import 'api.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: TipScreen(),
    );
  }
}

class TipScreen extends StatefulWidget {
  const TipScreen({super.key});

  @override
  State<TipScreen> createState() => _TipScreenState();
}

class _TipScreenState extends State<TipScreen> {
  bool liked = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Tip of the Day'),
        actions: [
          IconButton(
            icon: Icon(liked ? Icons.favorite : Icons.favorite_border),
            onPressed: () {
              setState(() {
                liked = !liked;
              });
            },
          ),
        ],
      ),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(24),
          child: FutureBuilder<String>(
              future: fetch('/tip'),
              builder: (context, snapshot) {
                if (snapshot.hasData) {
                  return Text(
                    snapshot.data!,
                    textAlign: TextAlign.center,
                    style: const TextStyle(fontSize: 24),
                  );
                }
                return const CircularProgressIndicator();
              },
            ),
        ),
      ),
    );
  }
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

데이터와 네트워크의 모든 레슨

직접 연습해 보세요: 온라인 Flutter 컴파일러