Flutter 全局状态管理Provider

1.Provider 全局状态管理

安装: pubspec.yaml
 
dependencies:
  provider: ^3.0.0+1
引入:
 
import 'package:provider/provider.dart';
自定义Store: store.dart
 
import 'package:provider/provider.dart'
    show ChangeNotifierProvider, MultiProvider, Consumer, Provider;
import 'model/storeData.dart' show UserInfo; //Model层
export 'model/storeData.dart'; //导出Model层
 
class Store {
  static init({context, child}) {
    //多个Provider
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(
          builder: (_) => UserInfo(),
        )
      ],
      child: child,
    );
  }
   
  //获取值 of(context)  这个会引起页面的整体刷新,如果全局是页面级别的
  static T value<T>(context) {
    return Provider.of<T>(context);
  }
   
  // 不会引起页面的刷新,只刷新了 Consumer 的部分,极大地缩小你的控件刷新范围
  static Consumer connect<T>({builder, child}) {
    return Consumer<T>(builder: builder, child: child);
  }
}
Model层的定义:storeData.dart
 
import 'package:flutter/material.dart' show ChangeNotifier;
 
class UserInfo with ChangeNotifier {
  String _name = "用户名";
  String testData = "测试数据"; //尽量私有变量定义
  String get name => _name;
 
  void setName(name) {
    _name = name;
    notifyListeners(); //通知更新数据
  }
 
  @override
  void dispose() {
    super.dispose();
  }
}
引用:
 
import 'package:flutter/material.dart';
import 'package:flutter_app/store.dart' show Store, UserInfo;
 
class MyIos extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return _MyIos();
  }
}
 
class _MyIos extends State<MyIos> {
  @override
  Widget build(BuildContext context) {
    print("ios 更新");
 
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text("Layout"),
      ),
      body: Column(
        children: <Widget>[
          Store.connect<UserInfo>(builder: (ctx, user, child) {
            return Text(user.name);
          }),
          //这个会引起整个页面重新build
          // RaisedButton(
          //   child: Text("修改数据"),
          //   onPressed: () {
          //     Store.value<UserInfo>(context).setName("234");
          //   },
          // ),
          Store.connect<UserInfo>(
              builder: (ctx, user, child) {
                return RaisedButton(
                  child: child,
                  onPressed: () {
                    user.setName("111");
                    
                  },
                );
              },
              child: Text("修改数据"))
        ],
      ),
    );
  }
}
配置: main.dart
 
class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    //这里是整个app的全局变量 
    return Store.init(
        context: context, //以这个为准
        child: MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            // This is the theme of your application.
            //
            // Try running your application with "flutter run". You'll see the
            // application has a blue toolbar. Then, without quitting the app, try
            // changing the primarySwatch below to Colors.green and then invoke
            // "hot reload" (press "r" in the console where you ran "flutter run",
            // or simply save your changes to "hot reload" in a Flutter IDE).
            // Notice that the counter didn't reset back to zero; the application
            // is not restarted.
            primarySwatch: Colors.blue,
          ),
          //注册路由
          routes: {
            "exp": (context) => Example(),
            "txt": (context) => MyText(),
            "btn": (context) => MyButton(),
            "fm": (context) => Fm(),
            "input": (context) => MyInput(),
            "row": (context) => MyRow(),
            "cons": (context) => MyCons(),
            "dec": (context) => Dec(),
            "container": (context) => Con(),
            "list": (context) => MyList(),
            "grid": (context) => MyGrid(),
            "custom": (context) => MyCustom(),
            "scroll": (context) => NocaScroll(),
            "bar": (context) => MyBar(),
            "pointer": (context) => MyPointer(),
            "ges": (context) => MyGesture(),
            "ani": (context) => MyAnimate(),
            "hero": (context) => MyHero(),
            "more": (context) => MorePage(),
            "http": (context) => MyHttp(),
            "check": (context) => MyCheck(),
            "component": (context) => MyComponent(),
            "ios": (context) => MyIos(),
          },
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        ));
  }
}
2.管理状态的最常见的方法

Widget管理自己的状态。
Widget管理子Widget状态。
混合管理(父Widget和子Widget都管理状态)。
   如何决定使用哪种管理方法?下面是官方给出的一些原则可以帮助你做决定:

如果状态是用户数据,如复选框的选中状态、滑块的位置,则该状态最好由父Widget管理。
如果状态是有关界面外观效果的,例如颜色、动画,那么状态最好由Widget本身来管理。
如果某一个状态是不同Widget共享的则最好由它们共同的父Widget管理。
在Widget内部管理状态封装性会好一些,而在父Widget中管理会比较灵活。有些时候,如果不确定到底该怎么管理状态,那么推荐的首选是在父widget中管理(灵活会显得更重要一些)。

2-1. Widget管理自身状态

// TapboxA 管理自身状态.
 
//------------------------- TapboxA ----------------------------------
 
class TapboxA extends StatefulWidget {
  TapboxA({Key key}) : super(key: key);
 
  @override
  _TapboxAState createState() => new _TapboxAState();
}
 
class _TapboxAState extends State<TapboxA> {
  bool _active = false;
 
  void _handleTap() {
    setState(() {
      _active = !_active;
    });
  }
 
  Widget build(BuildContext context) {
    return new GestureDetector(
      onTap: _handleTap,
      child: new Container(
        child: new Center(
          child: new Text(
            _active ? 'Active' : 'Inactive',
            style: new TextStyle(fontSize: 32.0, color: Colors.white),
          ),
        ),
        width: 200.0,
        height: 200.0,
        decoration: new BoxDecoration(
          color: _active ? Colors.lightGreen[700] : Colors.grey[600],
        ),
      ),
    );
  }
}
 2-2.父Widget管理子Widget的状态

// ParentWidget 为 TapboxB 管理状态.
 
//------------------------ ParentWidget --------------------------------
 
class ParentWidget extends StatefulWidget {
  @override
  _ParentWidgetState createState() => new _ParentWidgetState();
}
 
class _ParentWidgetState extends State<ParentWidget> {
  bool _active = false;
 
  void _handleTapboxChanged(bool newValue) {
    setState(() {
      _active = newValue;
    });
  }
 
  @override
  Widget build(BuildContext context) {
    return new Container(
      child: new 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 new GestureDetector(
      onTap: _handleTap,
      child: new Container(
        child: new Center(
          child: new Text(
            active ? 'Active' : 'Inactive',
            style: new TextStyle(fontSize: 32.0, color: Colors.white),
          ),
        ),
        width: 200.0,
        height: 200.0,
        decoration: new BoxDecoration(
          color: active ? Colors.lightGreen[700] : Colors.grey[600],
        ),
      ),
    );
  }
}
2-3. 混合状态管理

对于一些组件来说,混合管理的方式会非常有用。在这种情况下,组件自身管理一些内部状态,而父组件管理一些其他外部状态

在下面TapboxC示例中,手指按下时,盒子的周围会出现一个深绿色的边框,抬起时,边框消失。点击完成后,盒子的颜色改变。 TapboxC将其_active状态导出到其父组件中,但在内部管理其_highlight状态。这个例子有两个状态对象_ParentWidgetState和_TapboxCState。

_ParentWidgetStateC类:

管理_active 状态。
实现 _handleTapboxChanged() ,当盒子被点击时调用。
当点击盒子并且_active状态改变时调用setState()更新UI。
_TapboxCState 对象:

管理_highlight 状态。
GestureDetector监听所有tap事件。当用户点下时,它添加高亮(深绿色边框);当用户释放时,会移除高亮。
当按下、抬起、或者取消点击时更新_highlight状态,调用setState()更新UI。
当点击时,将状态的改变传递给父组件
//---------------------------- ParentWidget ----------------------------
 
class ParentWidgetC extends StatefulWidget {
  @override
  _ParentWidgetCState createState() => new _ParentWidgetCState();
}
 
class _ParentWidgetCState extends State<ParentWidgetC> {
  bool _active = false;
 
  void _handleTapboxChanged(bool newValue) {
    setState(() {
      _active = newValue;
    });
  }
 
  @override
  Widget build(BuildContext context) {
    return new Container(
      child: new 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;
 
  @override
  _TapboxCState createState() => new _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);
  }
 
  @override
  Widget build(BuildContext context) {
    // 在按下时添加绿色边框,当抬起时,取消高亮  
    return new GestureDetector(
      onTapDown: _handleTapDown, // 处理按下事件
      onTapUp: _handleTapUp, // 处理抬起事件
      onTap: _handleTap,
      onTapCancel: _handleTapCancel,
      child: new Container(
        child: new Center(
          child: new Text(widget.active ? 'Active' : 'Inactive',
              style: new TextStyle(fontSize: 32.0, color: Colors.white)),
        ),
        width: 200.0,
        height: 200.0,
        decoration: new BoxDecoration(
          color: widget.active ? Colors.lightGreen[700] : Colors.grey[600],
          border: _highlight
              ? new Border.all(
                  color: Colors.teal[700],
                  width: 10.0,
                )
              : null,
        ),
      ),
    );
  }
}
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值