Flutter: SnackBarが非表示になったタイミングで実行される処理の実装方法
はじめに
リスト内の要素をスワイプして削除できるようにする機能を個人開発で実装する場面があった。
スワイプ後にSnackBarでアクションの内容を通知し、それが表示されている間はアクションを取り消すことができてSnackBarが非表示になったタイミングでアクションの実行を完了させる、というものだ。
イメージとしては以下。

SnackBarは今までも処理結果の通知などでよく利用していたが、それが非表示になったタイミングで特定の処理を走らせるということは今まで実装したことがなかったので残しておく。
対応方法
SnackBarの表示にはScaffoldMessenger.of(context).showSnackBar(snackBar)を利用するが、このshowSnackBarメソッドはScaffoldFeatureController<SnackBar, SnackBarClosedReason>という返り値を持っている。
ScaffoldFeatureControllerのclosedというプロパティを使うことで、SnackBarClosedReasonというSnackBarがどうやって閉じられたかの情報を取得することができる。これを利用して閉じられた場面ごとに処理を出し分けることが可能になる。SnackBarClosedReasonはenumであり、利用できる値は以下。
enum SnackBarClosedReason {
  // SnackBarActionによって閉じられたとき
  action,
  // SemanticsAction.dismissによって閉じられたとき
  dismiss,
  // ユーザーがSnackBarをスワイプして閉じたとき
  swipe,
  // ScaffoldFeatureControllerのcloseコールバック、または、ScaffoldMessengerState.hideCurrentSnackBarを直接実行したとき
  hide,
  // ScaffoldMessengerState.removeCurrentSnackBarによって閉じられたとき
  remove,
  // 設定していたタイマーの時間が過ぎたとき
  timeout,
}
以下の実装例では、SnackBarAction以外でSnackBarが閉じられた際に処理を走らせている。
TextButton(
  onPressed: () async {
    // SnackBarの生成
    final snackBar = SnackBar(
      action: SnackBarAction(
        label: '元に戻す',
        onPressed: () {/* 処理 */},
      ),
      content: const Text('アーカイブしました'),
    );
    // SnackBarを表示し、閉じられた理由を取得する
    final controller = ScaffoldMessenger.of(context).showSnackBar(snackBar);
    final closedReason = await controller.closed;
    // SnackBarがアクションで閉じられた場合は処理を実行せず、それ以外の場合に処理を実行する
    if (closedReason != SnackBarClosedReason.action) {
      // SnackBarが非表示になったときの処理
    }
  },
  child: Text('ボタン'),
),
おわり
これでSnackBarが非表示になった際に処理を走らせることができるようになった。良きSnackBarライフを!