Research on state management of flutter

Time:2020-10-27

preface

Recently, I learned about the cross platform solution based on the app that wants to implement a common set of personal functions. And then began the study of flutter, through the article to record the harvest of learning.

The main content of this article is to introduce the mode of state management and the choice of different ways in flutter.

This article first appeared in my personal blog technology mansion( wcc.im )On the state management of flutter

catalog

  • preface
  • catalog
  • Mode of state management

    • It is managed by the widget itself
    • Managed by the parent widget
    • It is managed by the widget itself and the parent widget
  • The choice of state management mode

Mode of state management

There are three common state management methods, which are managed by the widget itself, managed by the parent widget, and managed by the widget itself and the parent widget.

In the analysis of three common state management methods, we define three tapboxes, each of which can represent active and inactive. In this way, tapbox is a stateful widget.

It is managed by the widget itself

//------------------------- TapboxA ----------------------------------

class TapboxA extends StatefulWidget {
  TapboxA({Key key}) : super(key: key);

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

class _TapboxAState extends State<TapboxA> {
  bool _active = false;

  void _handleTap() {
    setState(() {
      _active = !_active;
    });
  }

  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: _handleTap,
      child: Container(
        child: Center(
          child: Text(
            _active ? 'Active' : 'Inactive',
            style: TextStyle(fontSize: 32.0, color: Colors.white),
          ),
        ),
        width: 200.0,
        height: 200.0,
        decoration: BoxDecoration(
          color: _active ? Colors.lightGreen[700] : Colors.grey[600],
        ),
      ),
    );
  }
}

It is very simple to manage the state by widget itself, and the state class of tapboxa is responsible for state management. use_activeTo determine the current value and color and use the_handleTapTo change its value.

Managed by the parent widget

//------------------------ ParentWidget --------------------------------

class ParentWidget extends StatefulWidget {
  @override
  _ParentWidgetState createState() => _ParentWidgetState();
}

class _ParentWidgetState extends State<ParentWidget> {
  bool _active = false;

  void _handleTapboxChanged(bool newValue) {
    setState(() {
      _active = newValue;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: TapboxB(
        active: _active,
        onChanged: _handleTapboxChanged,
      ),
    );
  }
}

//------------------------- TapboxB ----------------------------------

class TapboxB extends StatelessWidget {
  TapboxB({Key key, this.active: false, @required this.onChanged})
      : super(key: key);

  final bool active;
  final ValueChanged<bool> onChanged;

  void _handleTap() {
    onChanged(!active);
  }

  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: _handleTap,
      child: Container(
        child: Center(
          child: Text(
            active ? 'Active' : 'Inactive',
            style: TextStyle(fontSize: 32.0, color: Colors.white),
          ),
        ),
        width: 200.0,
        height: 200.0,
        decoration: BoxDecoration(
          color: active ? Colors.lightGreen[700] : Colors.grey[600],
        ),
      ),
    );
  }
}

Managed by the parent widget, it mainly includes:

  • The parent widget manages the_activeStatus.
  • Implemented in the state class of the parent widget_handleTapboxChanged()

The main features of subwidget are as follows:

  • inheritStatelessWidgetClass because its state is managed by the parent widget.
  • Notify the parent widget when it is clicked instead of managing the state itself.

It is managed by the widget itself and the parent widget

//---------------------------- ParentWidget ----------------------------

class ParentWidget extends StatefulWidget {
  @override
  _ParentWidgetState createState() => _ParentWidgetState();
}

class _ParentWidgetState extends State<ParentWidget> {
  bool _active = false;

  void _handleTapboxChanged(bool newValue) {
    setState(() {
      _active = newValue;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: TapboxC(
        active: _active,
        onChanged: _handleTapboxChanged,
      ),
    );
  }
}

//----------------------------- TapboxC ------------------------------

class TapboxC extends StatefulWidget {
  TapboxC({Key key, this.active: false, @required this.onChanged})
      : super(key: key);

  final bool active;
  final ValueChanged<bool> onChanged;

  _TapboxCState createState() => _TapboxCState();
}

class _TapboxCState extends State<TapboxC> {
  bool _highlight = false;

  void _handleTapDown(TapDownDetails details) {
    setState(() {
      _highlight = true;
    });
  }

  void _handleTapUp(TapUpDetails details) {
    setState(() {
      _highlight = false;
    });
  }

  void _handleTapCancel() {
    setState(() {
      _highlight = false;
    });
  }

  void _handleTap() {
    widget.onChanged(!widget.active);
  }

  Widget build(BuildContext context) {
    // This example adds a green border on tap down.
    // On tap up, the square changes to the opposite state.
    return GestureDetector(
      onTapDown: _handleTapDown, // Handle the tap events in the order that
      onTapUp: _handleTapUp, // they occur: down, up, tap, cancel
      onTap: _handleTap,
      onTapCancel: _handleTapCancel,
      child: Container(
        child: Center(
          child: Text(widget.active ? 'Active' : 'Inactive',
              style: TextStyle(fontSize: 32.0, color: Colors.white)),
        ),
        width: 200.0,
        height: 200.0,
        decoration: BoxDecoration(
          color:
              widget.active ? Colors.lightGreen[700] : Colors.grey[600],
          border: _highlight
              ? Border.all(
                  color: Colors.teal[700],
                  width: 10.0,
                )
              : null,
        ),
      ),
    );
  }
}

You can see that this pattern is just a combination of the first two. In the example, the_highlightAdded the state of adding border on the edge of tapbox, which is managed by the widget itself, and_activeThe state is managed by the parent widget.

The choice of state management mode

In general, the mode of state management is as follows:

  • If the state in question is user data, such as the checked or unselected mode of a check box, or the position of the slider, it is best for the parent widget to manage the state.
  • If the state in question is animation, etc., it’s best for the widget itself to manage the state.

This article first appeared in my personal blog technology mansion( wcc.im )。
Link to the original text: https://wcc.im/zh/post/flutter-state-management/
All articles in this blog are original, and are licensed by CC by-nc-sa 4.0 license agreement. For use beyond the CC by-nc-sa 4.0 license agreement, please contact the author for authorization.