【Dart】try、catch、throwの使い方メモ
はじめに
フルゲンと申します。
以下Kboyさんの動画の
try、catch、throwについて学習した内容のメモになります。
YouTubeのvideoIDが不正です
サンプルなどは動画内のコードを使ってます。
わかりやすく説明されているので、こちらも参考にしてみてください。
どなたかの参考になれば幸いです。
間違い等ございましたらご指摘いただけるとありがたいです。
try、catch、throwについて
try、catch、throw文を使って例外を処理することができる。
try
通常処理を行うコードを入れる。tryで囲むと例外が発生するとcatch(e)のeに例外を入れてくれる。
catch
tryで発生した例外の処理をかく。
(例外インスタンスeの内容表示したり、スタックトレース表示したりして開発者に伝える。)
throw
例外が起きたことを開発者(システム?)に知らせる。
(アプリ上では表示は何もない。)
try、 catch、 throwを使ったバリデーションの具体例
前提
本の一覧を表示するページadd_book_page.dartと、
本の状態を管理するadd_book_model.dartがあるとします。
add_book_page.dartのaddBook()
内で、
add_book_model.dart内の本をfirestoreに追加するメソッド
addBookToFirestore()
を呼び出して何らかの処理しているとします。
今回はaddBook()
内の例外処理をしてみます。
1. 例外を捕まえたい処理をtry のbodyで囲み、例外が起きた時の処理をcatchのbodyでかく。
Future addBook(AddBookModel model, BuildContext context) async {
try {
//うまくいった場合のこと(通常処理)をかく
await model.addBookToFirebase();
...
} catch (e) {
//exceptionが発生した場合のことをかく。 今回はダイアログを出す。
showDialog(
...
);
}
}
2. try文の中で呼び出されるメソッド側でthrowを定義しておく
throwはtry文の中で呼び出されるメソッドのbodyの中でif文などを使って記述しておきます。
以下では「textが空っぽなら例外を投げる」という処理になります。
throwされると、メソッド内のthrow文から下は実行されず、
呼び出しもとのcatchに処理は飛びます。
Future addBookToFirebase() async {
//ここでバリデーションする
if (bookTitle.isEmpty) {
throw ('タイトル入力してください。');
}
// throwされると、ここから下は実行されず、呼び出し元のcatch文に飛ぶ
FirebaseFirestore.instance.collection('books').add({
'title': bookTitle,
'createdAt': Timestamp.now()
});
}
さらにこの上のthrow()
で定義しているtext(今回は''タイトル入力してください。'')
はcatch(e)
の e
に格納されるので、
e.toString
で呼び出すことができる。
以下実行例
Future addBook(AddBookModel model, BuildContext context) async {
try {
await model.addBookToFirebase();
} catch (e) {
//exceptionが発生した場合のことをかく
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
// addBookToFirebase()のthrowで定義した文章を
// e.toString()を使って表示している。
title: Text(e.toString()),
actions: <Widget>[
ElevatedButton(
child: Text('OK'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
}
AlertDialogの部分はこんな感じで表示されます。
注意
-
今回のようにthrowを含んでいるメソッドがFutureを返す場合は
メソッドを呼び出し側のtryにasync、メソッド呼び出し処理にawaitつける必要がある。
これをしないと、exceptionはtry内でキャッチされず、メソッドの次の文が実行されてしまいます。 -
本番のコードではExceptionを自分で定義する方法は推奨されていないとのことです。
Dartの用意しているFormatExceptionなどを使う方が良いかもしれません。
Creating instances of Exception directly with Exception("message") is discouraged in library code since it doesn't give users a precise type they can catch. It may be reasonable to use instances of this class in tests or during development.
Exception のインスタンスを Exception("message") で直接作成することは、ユーザーにキャッチできる正確な型を与えないため、ライブラリコードでは推奨されません。テストや開発中にこのクラスのインスタンスを使用することは、合理的かもしれません。
Exception class - dart:core library - Dart API
終わりに
ここまで読んでいただきありがとうございました!
参考
YouTubeのvideoIDが不正です
Discussion