カテゴリー
Flutter

Flutterの状態管理あれこれ

 状態管理の要点はその状態に影響を受けるWidgetのみが状態変化に対する処理を行えるように効率化することです。

InheritedWidget
 Flutter自身を構成するWidgetの一つ。Widgetツリーの配下に効率的に情報を伝える仕組みを提供します。

Flutter_InheritedWidget
Flutter_InheritedWidget
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(
        key: null,
        child: Scaffold(
          appBar: AppBar(
            title: Text("Inherited Widget Sample"),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                WidgetNumText(),
                WidgetCenterText(
                  key: null,
                ),
              ],
            ),
          ),
          floatingActionButton: WidgetIncrementBtn(),
        ),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({required Key? key, required this.child}) : super(key: key);

  final Widget child;

  @override
  _MyHomePageState createState() => _MyHomePageState();

  static _MyHomePageState of(BuildContext context, {bool rebuild = true}) {
    return rebuild
        ? (context.dependOnInheritedWidgetOfExactType<_InheritedWidget>()
                as _InheritedWidget)
            .data
        : (context
                .getElementForInheritedWidgetOfExactType<_InheritedWidget>()!
                .widget as _InheritedWidget)
            .data;
  }
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return _InheritedWidget(
      child: widget.child,
      data: this,
    );
  }
}

class WidgetIncrementButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final _MyHomePageState state = MyHomePage.of(context, rebuild: false);
    return FloatingActionButton(
      onPressed: () => state._incrementCounter(),
      tooltip: 'Increment',
      child: Icon(Icons.add),
    );
  }
}

class _InheritedWidget extends InheritedWidget {
  _InheritedWidget({
    Key? key,
    required Widget child,
    required this.data,
  }) : super(key: key, child: child);

  final _MyHomePageState data;

  @override
  bool updateShouldNotify(InheritedWidget oldWidget) => true;
}

class WidgetNumText extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final _MyHomePageState state = MyHomePage.of(context);
    return Text(
      '${state._counter}',
      style: Theme.of(context).textTheme.headline4,
    );
  }
}

class WidgetIncrementBtn extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final _MyHomePageState state = MyHomePage.of(context, rebuild: false);
    return FloatingActionButton(
      onPressed: () => state._incrementCounter(),
      tooltip: 'Increment',
      child: Icon(Icons.add),
    );
  }
}

class WidgetCenterText extends StatelessWidget {
  const WidgetCenterText({required Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Text('You have pushed the button this many times:');
  }
}

Memo
Shader compilation errorが出たら
エミュレーターからアプリを消してflutter cleanする


Provider
 InheritedWidgetのラッパークラスで状態管理とDI機能を提供します。

StateNotifer
状態管理パッケージでProviderをベースに作られている。同じ作者。