美文网首页
轻松flutter之 组件状态管理

轻松flutter之 组件状态管理

作者: 熊爸天下_56c7 | 来源:发表于2020-05-15 11:11 被阅读0次
    管理状态的最常见的方法:
    方法 描述
    自身状态管理 Widget管理自己的状态。
    父组件管理子组件状态 父Widget管理子Widget状态。
    混合管理 混合管理(父Widget和子Widget都管理状态)。
    全局状态管理 使用第三方库进行全局状态管理
    关于状态管理原则:
    • 如果状态是用户数据,如复选框的选中状态、滑块的位置,则该状态最好由父Widget管理。
    • 如果状态是有关界面外观效果的,例如颜色、动画,那么状态最好由Widget本身来管理。
    • 如果某一个状态是不同Widget共享的则最好由它们共同的父Widget管理。

    在Widget内部管理状态封装性会好一些,而在父Widget中管理会比较灵活。有些时候,如果不确定到底该怎么管理状态,那么推荐的首选是在父widget中管理(灵活会显得更重要一些)。

    一. 组件自身管理自身状态

    自己管理自己的状态比较简单, 参数在组件内部 , 同时 setState也在自己内部

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text("组件自己管理自己状态"),
          ),
          body: SelfWidget(),
        );
      }
    }
    
    class SelfWidget extends StatefulWidget {
      @override
      _SelfWidgetState createState() => _SelfWidgetState();
    }
    
    class _SelfWidgetState extends State<SelfWidget> {
      bool _isActive = false;
      _handleTap() {
        setState(() {
          _isActive = !_isActive;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return GestureDetector(
          onTap: _handleTap,
          child: Container(
            width: 200,
            height: 200,
            color: _isActive ? Colors.amber : Colors.blueAccent,
          ),
        );
      }
    }
    

    二. 父组件管理子组件

    父组件将参数和方法传给子组件供子组件调用, 子组件调用方法其实是在父组件中setState了.
    子组件可以是无状态组件, 因为它并没有管理自身状态

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text("父组件管理子组件状态"),
          ),
          body: ParentsWidget(),
        );
      }
    }
    
    class ParentsWidget extends StatefulWidget {
      @override
      _ParentsWidgetState createState() => _ParentsWidgetState();
    }
    
    class _ParentsWidgetState extends State<ParentsWidget> {
      bool _isActive = false;
      void _tapToChangeColor(v) {
        setState(() {
          _isActive = v;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return SonWidget(isActive: _isActive, tapFunction: _tapToChangeColor);
      }
    }
    
    class SonWidget extends StatelessWidget {
      SonWidget({Key key, this.isActive, this.tapFunction}) : super(key: key);
      final bool isActive;
      final Function tapFunction;
      void _handleTap() {
        tapFunction(!isActive);
      }
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: GestureDetector(
            child: Container(
              width: 200,
              height: 200,
              color: isActive ? Colors.amber : Colors.blue,
            ),
            onTap: _handleTap,
          ),
        );
      }
    }
    

    三. 混合管理

    如果子组件是有状态组件, 那么它可被父组件管理, 也可以自己管理自己.那么可以根据状态的重要性采取不同的管理方式吗?? 可以!
    混合管理可以简单理解为: 父组件接管子组件一部分状态, 子组件再自己管理一些仅与自己相关的状态

    如下例: 框内颜色是父组件接管的 边框颜色是 自身管理的.

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text("混合管理"),
          ),
          body: ParentsWidget(),
        );
      }
    }
    
    class ParentsWidget extends StatefulWidget {
      @override
      _ParentsWidgetState createState() => _ParentsWidgetState();
    }
    
    class _ParentsWidgetState extends State<ParentsWidget> {
      bool _isActive = false; //这个状态是父组件管理的, 给子组件用
      void _tapToChangeColor(v) {
        setState(() {
          _isActive = v; //父组件接管管理的状态在此更新
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return SonWidget(isActive: _isActive, tapFunction: _tapToChangeColor);
      }
    }
    
    class SonWidget extends StatefulWidget {
      final bool isActive;
      final Function tapFunction;
      SonWidget({Key key, this.isActive, this.tapFunction}) : super(key: key);
      @override
      _SonWidgetState createState() => _SonWidgetState();
    }
    
    class _SonWidgetState extends State<SonWidget> {
      bool _borderHighLight = false; //这个状态是自己管理的
      void _handleTap() {
        widget.tapFunction(!widget.isActive); //这个状态是父组件管理的
        setState(() {
          _borderHighLight = !_borderHighLight; //自己管理的状态在此更新
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: GestureDetector(
            child: Container(
              width: 200,
              height: 200,
              child: Container(
                color: widget.isActive ? Colors.amber : Colors.blueAccent,
              ),
              decoration: BoxDecoration(
                  border: Border.all(
                      color: _borderHighLight ? Colors.blueAccent : Colors.amber,
                      width: 10)),
            ),
            onTap: _handleTap,
          ),
        );
      }
    }
    

    四. 全局状态管理 (第三方provider库)

    有时候, 可能有一个状态是整个APP都要用的 比如:账号状态 等.这就需要我们做全局状态管理了
    全局状态管理由多种方法, 这里我们使用一种比较简单的

    https://pub.dev/packages/provider#-readme-tab-

    这里我只用了比较旧的版本

    provider: ^2.0.1+1
    

    用法:

    import 'package:flutter/foundation.dart';
    import 'package:flutter/material.dart';
    import 'package:provider/provider.dart';
    
    main() {
      runApp(ChangeNotifierProvider<Counter>.value(
        notifier: Counter(1), 
        child: MyApp(),
      ));
    }
    
    class Counter with ChangeNotifier {
      int _count;
      Counter(this._count);
    
      void add() {
        _count++;
        notifyListeners(); 
      }
    
      void sub() {
        _count--;
        notifyListeners(); 
      }
    
      get count => _count; 
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text("全局状态管理(provide库)"),
          ),
          body: FirstWidget(),
        );
      }
    }
    
    class FirstWidget extends StatefulWidget {
      @override
      _FirstWidgetState createState() => _FirstWidgetState();
    }
    
    class _FirstWidgetState extends State<FirstWidget> {
      @override
      Widget build(BuildContext context) {
        return Center(
          child: Column(
            children: <Widget>[
              Text(
                "这里有一个公用状态数据:${Provider.of<Counter>(context)._count}",
                style: TextStyle(fontSize: 30),
              ),
              RaisedButton.icon(
                  onPressed: () {
                    print("object");
                    Provider.of<Counter>(context).add();
                  },
                  icon: Icon(Icons.add_box),
                  label: Text("增大")),
              RaisedButton.icon(
                  onPressed: () {
                    Provider.of<Counter>(context).sub();
                  },
                  icon: Icon(Icons.low_priority),
                  label: Text("减小")),
              RaisedButton.icon(
                  onPressed: () {
                    Navigator.of(context).push(
                        MaterialPageRoute(builder: (context) => SecondPage()));
                  },
                  icon: Icon(Icons.remove_red_eye),
                  label: Text("看一看下一页能不能改变")),
            ],
          ),
        );
      }
    }
    
    class SecondPage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
              title: Text("第二页"),
            ),
            body: Column(
              children: <Widget>[
                Text(
                  "这是'下一页',这里面看一下全局状态:${Provider.of<Counter>(context)._count}",
                  style: TextStyle(fontSize: 30),
                ),
                RaisedButton.icon(
                    onPressed: () {
                      print("object");
                      Provider.of<Counter>(context).add();
                    },
                    icon: Icon(Icons.add_box),
                    label: Text("增大")),
                RaisedButton.icon(
                    onPressed: () {
                      Provider.of<Counter>(context).sub();
                    },
                    icon: Icon(Icons.low_priority),
                    label: Text("减小")),
              ],
            ));
      }
    }
    

    相关文章

      网友评论

          本文标题:轻松flutter之 组件状态管理

          本文链接:https://www.haomeiwen.com/subject/zojqohtx.html