Flutter小白實操之Widgets狀態管理

以下內容參考《Flutter中文開發者社區》和《Flutter實戰·第二版》,僅為個人學習、熟悉Flutter,不同版本可能有稍微不一樣。

環境

///
/// 例子來源:
/// Widgets 介紹:https://flutter.cn/docs/development/ui/widgets-intro
/// 《Flutter實戰·第二版》:https://book.flutterchina.club/chapter2/state_manage.html
///
/// 環境:
/// Flutter 3.10.1 ? channel stable ? https://github.com/flutter/flutter.git
/// Framework ? revision d3d8effc68 (7 days ago) ? 2023-05-16 17:59:05 -0700
/// Engine ? revision b4fb11214d
/// Tools ? Dart 3.0.1 ? DevTools 2.23.1
///

管理狀態的最常見的方法:

  • Widget 管理自己的狀態。
  • Widget 管理子 Widget 狀態。
  • 混合管理(父 Widget 和子 Widget 都管理狀態)。

如何決定使用哪種管理方法?下面是官方給出的一些原則可以幫助你做決定:

  • 如果狀態是用戶數據,如復選框的選中狀態、滑塊的位置,則該狀態最好由父 Widget 管理。
  • 如果狀態是有關界面外觀效果的,例如顏色、動畫,那么狀態最好由 Widget 本身來管理。
  • 如果某一個狀態是不同 Widget 共享的則最好由它們共同的父 Widget 管理。

Widget 管理自己的狀態

/// TapBoxA 管理自身狀態.
class TapBoxA extends StatefulWidget {
  const TapBoxA({super.key});

  @override
  State<TapBoxA> createState() => _TapBoxAState();
}

class _TapBoxAState extends State<TapBoxA> {
  bool _active = false;

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

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

Widget 管理子 Widget 狀態。

/// ParentWidget 為 TapBoxB 管理狀態.
/// ------------------------ ParentWidget --------------------------------
class ParentWidget extends StatefulWidget {
  const ParentWidget({super.key});

  @override
  State<ParentWidget> createState() => ParentWidgetState();
}

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

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("父管理子Widget的狀態"),
        backgroundColor: Colors.black,
      ),
      body: TapBoxB(
        active: _active,
        onChanged: handleTapBoxChange,
      ),
    );
  }
}

///------------------------ TapBoxB ----------------------------------
class TapBoxB extends StatelessWidget {
  const TapBoxB({super.key, this.active = false, required this.onChanged});

  final bool active;
  final ValueChanged<bool> onChanged;

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

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: _handleTap,
      child: Center(
        child: Container(
          width: 200.0,
          height: 200.0,
          decoration: BoxDecoration(
            color: active ? Colors.red[700] : Colors.blue[600],
          ),
          child: Center(
            child: Text(
              active ? "Active" : "Inactive",
              style: const TextStyle(fontSize: 30, color: Colors.white),
            ),
          ),
        ),
      ),
    );
  }
}
Widget 管理子 Widget 狀態

混合狀態管理

/// ------------------------ ParentWidgetC --------------------------------
class ParentWidgetC extends StatefulWidget {
  const ParentWidgetC({super.key});

  @override
  State<ParentWidgetC> createState() => _ParentWidgetCState();
}

class _ParentWidgetCState extends State<ParentWidgetC> {
  bool _activeState = false;

  void _handleTabBoxChange(bool newValue) {
    setState(() {
      _activeState = newValue;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("混合狀態管理", style: TextStyle(color: Colors.white)),
        backgroundColor: Colors.blue[500],
      ),
      body: TapBoxC(
        active: _activeState,
        onChanged: _handleTabBoxChange,
      ),
    );
  }
}

///----------------------------- TapBoxC ------------------------------
class TapBoxC extends StatefulWidget {
  const TapBoxC({super.key, this.active = false, required this.onChanged});

  final bool active;
  final ValueChanged<bool> onChanged;

  @override
  State<TapBoxC> 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() {
    setState(() {
      widget.onChanged(!widget.active);
    });
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: handleTap,
      onTapDown: handleTapDown,
      onTapUp: handleTapUp,
      onTapCancel: handleTapCancel,
      child: Center(
        child: Container(
          width: 200.0,
          height: 200.0,
          decoration: BoxDecoration(
            color: widget.active ? Colors.pink[200] : Colors.cyan[500],
            border: highlight
                ? Border.all(color: Colors.orange[700]!, width: 10,)
                //Border(top: BorderSide(color: Colors.orange[700]!, width: 10))
                : null,
          ),
          child: Center(
            child: Text(
              widget.active ? "Active" : "Inactive",
              style: const TextStyle(fontSize: 30, color: Colors.white),
            ),
          ),
        ),
      ),
    );
  }
}
混合狀態管理
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。