LoginSignup
1
0

[Flutter] InheritedWidget

Last updated at Posted at 2024-03-13

はじめに

FlutterのInheritedWidgetについての記事です。
詳しい原理などは省いて、使い方について言及します。
(詳しい原理については別途記事を作成しようと思います)

InheritedWidget

データを子Widgetへ効率的に伝えるWidgetです

特徴

  • 子WidgetはO(1)でInheritedWidgetへアクセスが可能
  • InheritedWidgetが提供するデータに変化があった場合、必要に応じて子Widgetのリビルドが可能

使い方

  • InheritedWidget継承クラスを作成する
  • 子WidgetからInheritedWidgetのメソッドを使用してデータを参照する

InheritedWidget継承クラスを作成する

inherited_sample.dart

class InheritedText extends InheritedWidget {
  const InheritedText({
    super.key,
    required this.text,
    required super.child,
  });

  final String text;

  /// InheritedWidget継承クラスを取得する為の関数です
  /// 参照元Widgetから最も近いInheritedWidget継承クラスを取得します
  static InheritedText? maybeOf(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<InheritedText>();
  }

  static InheritedText of(BuildContext context) {
    final InheritedText? result = maybeOf(context);
    assert(result != null, 'No InheritedCounter found in context');
    return result!;
  }

  /// InheritedWidget継承クラスがリビルドされた時に
  /// データを参照しているWidgetをリビルドさせるかを判定するメソッドです
  @override
  bool updateShouldNotify(InheritedText oldWidget) =>
      text != oldWidget.text;
}

子WidgetからInheritedWidgetのメソッドを使用してデータを参照する

inherited_sample.dart

class TextDisplayWidget extends StatelessWidget {
  const TextDisplayWidget({super.key});

  @override
  Widget build(BuildContext context) {

    ///
    /// InheritedTextのofメソッドを使用して、textを参照しています
    final text = InheritedText.of(context).text;
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text("InheritedWidgetお試し"),
      ),
      body: Center(
        child: Text(text),
      ),
    );
  }
}

コード全体

inherited_sample.dart

void main() {
  runApp(const InheritedSampleApp());
}

class InheritedText extends InheritedWidget {
  const InheritedText({
    super.key,
    required this.text,
    required super.child,
  });

  final String text;

  /// InheritedWidget継承クラスを取得する為の関数です
  /// 参照元Widgetから最も近いInheritedWidget継承クラスを取得します
  static InheritedText? maybeOf(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<InheritedText>();
  }

  static InheritedText of(BuildContext context) {
    final InheritedText? result = maybeOf(context);
    assert(result != null, 'No InheritedCounter found in context');
    return result!;
  }

  /// InheritedWidget継承クラスがリビルドされた時に
  /// データを参照しているWidgetをリビルドさせるかを判定するメソッドです
  @override
  bool updateShouldNotify(InheritedText oldWidget) => text != oldWidget.text;
}

class InheritedSampleApp extends StatelessWidget {
  const InheritedSampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const InheritedText(
        text: "テストだよ",
        child: TextDisplayWidget(),
      ),
    );
  }
}

class TextDisplayWidget extends StatelessWidget {
  const TextDisplayWidget({super.key});

  @override
  Widget build(BuildContext context) {

    ///
    /// InheritedTextのofメソッドを使用して、textを参照しています
    final text = InheritedText.of(context).text;
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text("InheritedWidgetお試し"),
      ),
      body: Center(
        child: Text(text),
      ),
    );
  }
}

注意点

ofメソッド、というよりもdependOnInheritedWidgetOfExactTypeメソッドは下記では呼ばないようにしましょう

  • StatefulWidgetのinitStateメソッド内
    • initStateはStatefulWidgetのリビルドで毎回呼ばれるものではない為です
    • 上位のinheritedWidgetの更新を正しく受け取りたい場合はdidChangeDependencies内で呼ぶ必要があります
  • StatefulWidgetのdisposeメソッド内
    • dispose時点ではElementツリーが既に不安定に成っている為です
    • BuildContextを使用して参照を得ているのでElementツリーの状態は常に考慮する必要があると思います

まとめ

以上がinheritedWidgetの基本的な使用方法です。
今回の例はinheritedWidgetのデータは常に変化しないようになっていますが、StatefulWidget等と併用する事で変更が可能です。

適切ではない点などあればご指摘いただけると幸いです。

参考資料

1
0
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
1
0