美文网首页
轻松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