finally로 정리하기
Coddy Flutter 여정의 데이터와 네트워크 섹션에 포함된 레슨. 27개 중 12번째.
호출이 성공하든 실패하든 반드시 해야 하는 작업이 있습니다. 스피너를 숨기거나 버튼을 다시 활성화하는 일입니다. 이를 try와 catch에 각각 작성하다 보면 둘 중 한 곳을 빠뜨리기 쉽습니다. Dart에는 이를 위한 세 번째 블록인 finally가 있습니다.
try {
await saveName(name);
} catch (e) {
// 오류를 표시합니다
} finally {
// 항상 실행됩니다: try 이후 또는 catch 이후
}finally는 매번 마지막에 실행됩니다. 성공하면 try 다음에, 실패하면 catch 다음에 실행됩니다. 따라서 호출 전에 설정한 것을 원래대로 되돌리는 작업을 한곳에서 처리할 수 있습니다.
여기서는 앱이 저장하는 동안 저장 버튼을 회색으로 비활성화합니다. 이때 onPressed: saving ? null : save를 사용합니다. onPressed가 null인 버튼은 누를 수 없습니다. saving이 다시 false가 되지 않으면 버튼은 계속 회색으로 비활성화된 상태로 남습니다.
챌린지
중급필드를 비운 채 저장하세요. 오류가 표시되고 저장 버튼이 회색으로 유지되어 다시 시도할 수 없습니다. saving = false를 try 블록에서 꺼내 별도의 setState 안에 있는 finally 블록으로 옮기세요.
직접 해보기
import 'package:flutter/material.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: NameScreen(),
);
}
}
class NameScreen extends StatefulWidget {
const NameScreen({super.key});
@override
State<NameScreen> createState() => _NameScreenState();
}
class _NameScreenState extends State<NameScreen> {
final controller = TextEditingController();
String status = '';
bool saving = false;
@override
void dispose() {
controller.dispose();
super.dispose();
}
Future<void> saveName(String name) async {
await Future.delayed(const Duration(seconds: 1));
if (name.isEmpty) {
throw Exception('The name cannot be empty');
}
}
Future<void> save() async {
setState(() {
saving = true;
});
try {
await saveName(controller.text);
setState(() {
status = 'Saved: ${controller.text}';
saving = false;
});
} catch (e) {
setState(() {
status = '$e';
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: controller,
decoration: const InputDecoration(labelText: 'Name'),
),
const SizedBox(height: 16),
ElevatedButton(onPressed: saving ? null : save, child: const Text('Save')),
const SizedBox(height: 16),
Text(status, style: const TextStyle(fontSize: 18)),
],
),
),
);
}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
데이터와 네트워크의 모든 레슨
직접 연습해 보세요: 온라인 Flutter 컴파일러