[Flutter] 状態管理:InheritedWidget の使い方

Flutterでは、InheritedWidgetとBuildContextを使用して、状態を簡単かつ効率的に管理できます。InheritedWidgetは、親Widgetから子Widgetに状態を伝えるための一種のコンテナであり、BuildContextは、Widgetの構築中に使用されるビルドコンテキストの一種です。この記事では、FlutterのInheritedWidgetとBuildContextを使用した状態管理について、詳しい使い方を紹介します。

目次

InheritedWidgetとは?

InheritedWidgetは、親Widgetから子Widgetに状態を伝えるために使用されます。一般的には、ビルド中に変更されることのないデータを伝えるために使用されます。例えば、アプリのテーマやロケールなどの情報がInheritedWidgetに保存されることがあります。

InheritedWidgetは、自身を更新することはできず、新しいInheritedWidgetインスタンスを作成する必要があります。親WidgetでInheritedWidgetのインスタンスが変更されると、それに依存する子Widgetは自動的に再ビルドされます。このため、InheritedWidgetを使用すると、状態を簡単かつ効率的に管理できます。

InheritedWidgetを使用した状態管理の基本的な使い方

InheritedWidgetを使用して状態を管理するには、次の手順が必要です。

  1. InheritedWidgetを作成する
  2. InheritedWidgetを提供する親Widgetを作成する
  3. InheritedWidgetに依存する子Widgetを作成する

以下に、それぞれの手順について詳しく説明します。

1. InheritedWidgetを作成する

InheritedWidgetを作成するには、次の手順が必要です。

  1. InheritedWidgetを継承する
  2. InheritedWidgetに伝えたい状態を定義する
  3. InheritedWidgetに、状態を取得するためのメソッドを追加する

例えば、アプリのテーマを管理するInheritedWidgetを作成する場合、次のようなコードを記述することができます。

class ThemeState extends InheritedWidget {
  final ThemeData themeData;
  ThemeState({Key? key, required Widget child, required this.themeData})
      : super(key: key, child: child);

  static ThemeState? of(BuildContext context) =>
      context.dependOnInheritedWidgetOfExactType<ThemeState>();

  @override
  bool updateShouldNotify(covariant ThemeState oldWidget) =>
      oldWidget.themeData != themeData;
}

このコードでは、ThemeStateというInheritedWidgetを定義しています。themeDataというフィールドは、アプリのテーマデータを格納するために使用されます。ofメソッドは、BuildContextからThemeStateインスタンスを取得するために使用されます。updateShouldNotifyメソッドは、InheritedWidgetが更新されたかどうかを判断するために使用されます。

2. InheritedWidgetを提供する親Widgetを作成する

InheritedWidgetを提供する親Widgetを作成するには、次の手順が必要です。

  1. InheritedWidgetを含める
  2. InheritedWidgetをビルドする

例えば、アプリのルートWidgetであるMyAppWidgetが親Widgetであり、InheritedWidgetであるThemeStateを提供する場合、次のようなコードを記述することができます。

class MyAppWidget extends StatefulWidget {
  const MyAppWidget({Key? key}) : super(key: key);

  @override
  _MyAppWidgetState createState() => _MyAppWidgetState();
}

class _MyAppWidgetState extends State<MyAppWidget> {
  ThemeData _themeData = ThemeData.light();

  void _toggleTheme() {
    setState(() {
      _themeData = _themeData == ThemeData.light()
          ? ThemeData.dark()
          : ThemeData.light();
    });
  }

  @override
  Widget build(BuildContext context) {
    return ThemeState(
      themeData: _themeData,
      child: MaterialApp(
        title: 'My App',
        home: HomePage(
          onThemeToggle: _toggleTheme,
        ),
      ),
    );
  }
}

このコードでは、MyAppWidgetがThemeStateを提供しています。_themeDataというフィールドは、現在のテーマデータを保持するために使用されます。_toggleThemeメソッドは、テーマを切り替えるために使用されます。buildメソッドでは、ThemeStateを使用して、_themeDataを提供し、childには、アプリのルートWidgetであるMaterialAppを設定しています。

3. InheritedWidgetに依存する子Widgetを作成する

InheritedWidgetに依存する子Widgetを作成するには、次の手順が必要です。

  1. InheritedWidgetを使用して状態を取得する
  2. 状態に基づいてWidgetを構築する

例えば、アプリのホームページであるHomePageWidgetが、テーマを切り替えるためのボタンを提供する場合、次のようなコードを記述することができます。

class HomePage extends StatelessWidget {
  final VoidCallback onThemeToggle;
  const HomePage({Key? key, required this.onThemeToggle}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final themeData = ThemeState.of(context)!.themeData;

    return Scaffold(
      appBar: AppBar(
        title: Text('My App'),
      ),
      body: Center(
        child: Text(
          'Hello, World!',
        style: TextStyle(
          fontSize: 24,
          fontWeight: FontWeight.bold,
          color: themeData.primaryColor,
        ),
      ),
    ),
    floatingActionButton: FloatingActionButton(
      onPressed: onThemeToggle,
      child: Icon(Icons.color_lens),
    ),
  );
 }
}

このコードでは、HomePageWidgetがThemeStateに依存しています。ofメソッドを使用して、現在のテーマデータを取得しています。テーマデータを使用して、テキストの色を設定しています。また、floatingActionButtonは、テーマを切り替えるためのボタンであり、onThemeToggleコールバックを呼び出して、MyAppWidgetで定義された_toggleThemeメソッドを呼び出します。

InheritedWidgetを使用して状態を管理する方法について、詳細に説明しました。InheritedWidgetを使用すると、Flutterの状態管理についての理解が深まり、アプリケーションのパフォーマンスが向上する可能性があります。しかし、InheritedWidgetは、複雑なアプリケーションでは十分に使いやすいとは限りません。その場合は、別の状態管理の方法を検討する必要があります。

InheritedWidget以外の状態管理の方法は以下の記事および、記事内のリンクページにそれぞれの詳しい使い方の説明を記載していますので、参考にしてみて下さい。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次