9
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Flutter] mountedとは?

Last updated at Posted at 2024-04-22

mountedとは?

Flutterでは、ウィジェットがマウントされているかどうかを確認するために
mounted プロパティが提供されています。

このプロパティは、ウィジェットが現在のウィジェットツリーに含まれていて、
描画されているかどうかを確認するためのプロパティです。

特に、非同期処理やWidgetのライフサイクルを超えて操作を行う場合に使用されます。

Widgetがツリーに追加されると、mountedtrueに設定され、
一方、Widgetがツリーから削除された場合(新しい画面に遷移したときや、
親Widgetが削除されたときなど)、mountedfalseに設定されます。

mounted のチェックを行わない場合、例外が発生したり、
予期しない動作につながる可能性があるので、
WidgetのステートやUIを変更する操作を行う前には、
必ず mounted の値をチェックすることが重要です。

使用理由

mounted プロパティを使用する主な理由とメリットは以下の通りです。

1. Widgetのライフサイクルを適切に管理する

Widgetがウィジェットツリーから削除された後にステートを変更しようとするのを
防ぐことができます。これにより、不必要な例外やクラッシュを回避できます。

2. メモリリークを防ぐ

Widgetがアンマウントされた後に非同期処理が完了した場合、
その結果を処理しようとするとメモリリークが発生する可能性があります。
mounted プロパティを使用することで、不要な処理を行わずにリソースを管理できるため、
メモリリークを防ぐことにも繋がります。

3. パフォーマンスの向上

不要な処理を行わずに済むことで、アプリのパフォーマンスが向上します。
Widgetがアンマウントされた後に無駄な処理を行うことがなくなるため、
リソースを効率的に使用できます。

4. コードの堅牢性の向上

予期せぬ状況でのエラーを回避できます。これにより、コードの堅牢性が向上し、
安定したアプリケーションを構築できます。

5. デバッグの容易性

Widgetのライフサイクルに関するエラーを特定しやすくなります。
これにより、デバッグが容易になり、開発効率が向上します。

使用例

例えば、StatefulWidgetでAPIからデータを非同期で取得する場合を考えてみましょう。
Widgetが fetchData メソッドの完了前にウィジェットツリーから削除された場合、
そのWidgetのステートを更新しようとするとエラーが発生する可能性があります。

このような問題を回避するために、WidgetのステートやUIを変更する前には、
必ずmountedの値をチェックする必要があります。

以下は、非同期処理でmountedを使用する例です。

// StatefulWidgetの中で使用される
Future<void> fetchData() async {
  final data = await someAsyncOperation();
  if (mounted) {
    setState(() {
      // 取得したデータでWidgetのステートを更新
      _data = data;
    });
  }
}

この例では、 fetchData メソッドが非同期処理( someAsyncOperation )を
実行しています。取得したデータでWidgetのステートを更新する前に、
mounted の値をチェックしています。

もしWidgetがアンマウント(別の画面に遷移したり削除された場合)されていれば、
setState の呼び出しをスキップし、エラーの発生を防いでいます。

mounted を使用する場面は以下のような場合が想定されます。

  • WidgetのステートやUIを変更する前
  • 非同期処理、タイマー、Widgetのライフサイクルを超えて操作を行う場合

使い方

以下は、 mounted プロパティを使用した例です。

class _MyWidgetState extends State<MyWidget> {
  void _handleCallback() {
    if (mounted) {
      setState(() {
        // ステートを更新する処理
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () {
        // 別のWidgetからコールバック関数を呼び出す
        someOtherWidget.callbackFunction = _handleCallback;
      },
      child: const Text('Update State'),
    );
  }
}

この例では、ボタンを押すと別のWidgetからコールバック関数が呼び出されます。
コールバック関数内でステートを更新するため、 mounted のチェックが必要になります。

コールバック関数が呼び出された時点でWidgetがアンマウントされていた場合、
mounted チェックを行わずに setState() を呼び出すとエラーになってしまいます。
そのため、 mounted チェックを行った上でステートを更新する必要があります。

mounted 判定を行わずに setState() を呼び出した場合、
"setState() or markNeedsBuild() called during build"というエラーが発生する
可能性があります。これは、ビルドフェーズ中にステートが
変更されたことを示すエラーです。

注意点

mounted プロパティを使用する際には、ウィジェットが破棄された後に
アクセスされる可能性があるため、そのことを考慮する必要があります。
ウィジェットがマウントされていない場合にアクセスすると、
エラーが発生する可能性がありますので、適切にチェックすることが重要です。

まとめ

mounted プロパティを理解し、適切に使用することで、
Widgetのライフサイクルの変更を適切に処理し、アンマウントされたWidgetを
操作することによる問題を回避できるようになります。

特に非同期処理やWidgetのライフサイクルが複雑になる場合は、
mounted プロパティの使用が必須となります。これを機にぜひ使用してみてください。

参考資料

告知

最後にお知らせとなりますが、イーディーエーでは一緒に働くエンジニアを
募集しております。詳しくは採用情報ページをご確認ください。

みなさまからのご応募をお待ちしております。

9
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?