finallyで後処理する
CoddyのFlutterジャーニー「データとネットワーク」セクションの一部。レッスン 12/27。
呼び出しが成功しても失敗しても、必ず行う処理があります。スピナーを非表示にしたり、ボタンを再び有効にしたりする処理です。これを try と catch の両方に書くと、どちらか一方に書き忘れがちです。Dartには、そのための3つ目のブロック finally があります。
try {
await saveName(name);
} catch (e) {
// エラーを表示する
} finally {
// 常に実行される:try の後、または catch の後
}finally は必ず最後に実行されます。成功した場合は try の後に、失敗した場合は catch の後に実行されます。そのため、呼び出しの前に設定したものを元に戻す処理を書く場所として最適です。
ここでは、アプリは保存中に Save ボタンをグレー表示にします。これは onPressed: saving ? null : save によって行われます。onPressed が null のボタンは押せません。saving が false に戻らなければ、ボタンはずっとグレー表示のままです。
チャレンジ
中級フィールドが空の状態で保存すると、エラーが表示され、保存がグレーのままなので、再試行できません。saving = falseをtryブロックの外にあるfinallyブロックに移し、独立したsetStateの中に置きます。
自分で試してみよう
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オンラインコンパイラ