Flutter-Widget管理状态的三种方式

1.自身管理自己

_TapboxAState 类:

  • 管理TapboxA的状态。
  • 定义_active:确定盒子的当前颜色的布尔值。
  • 定义_handleTap()函数,该函数在点击该盒子时更新_active,并调用setState()更新UI。
  • 实现widget的所有交互式行为。
// TapboxA 管理自身状态.

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

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

  

 

2.父类管理自己

栗子:

在以下示例中,TapboxB通过回调将其状态导出到其父组件,状态由父组件管理,因此它的父组件为StatefulWidget。但是由于TapboxB不管理任何状态,所以TapboxBStatelessWidget

ParentWidgetState 类:

  • 为TapboxB 管理_active状态。
  • 实现_handleTapboxChanged(),当盒子被点击时调用的方法。
  • 当状态改变时,调用setState()更新UI。

TapboxB 类:

  • 继承StatelessWidget类,因为所有状态都由其父组件处理。
  • 当检测到点击时,它会通知父组件。

 

// 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],            
        ),                                                                       
      ),                                                                         
    );                                                                           
  }                                                                             
}                                                                               

再加上主app的代码,将home页设为ParentWidget:

void main() => runApp(new MyApp());                                                                      
                                                                                                         
class MyApp extends StatelessWidget {                                                                    
  @override                                                                                              
  Widget build(BuildContext context) {                                                                   
    return new MaterialApp(//程序主体Material App             c                                              
      title: 'Flutter Demo',                                                                             
      initialRoute: "/",                                                                                 
      theme: new ThemeData(                                                                              
        primarySwatch: Colors.blue,                                                                      
      ),                                                                                                  
        //注册路由表                                                                                          
        routes:{                                                                                         
          //"new_page":(context) => NewRoute(),                                                          
          //"new_page":(context) => EchoRoute(),                                                         
          //"/":(context) => MyHomePage(title: 'Flutter Demo Home Page'), //注册首页路由                       
          //"Counter":(context) => CounterWidget(),                                                      
        },                                                                                               
        //home: new MyHomePage(title: 'Flutter Demo Home Page'),                                         
        home:ParentWidget(),                                                                             
    );                                                                                                    
  }                                                                                                      
}                                                                                                        
                                                                                                         

 

运行截图如下:

 

 

3.

混合状态管理

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

class ParentWidgetC extends StatefulWidget {
  @override
  _ParentWidgetCState createState() => new _ParentWidgetCState();
}

class _ParentWidgetCState extends State<ParentWidgetC> {
  bool _active = false;  //这里保存实际tapboxC是否激活的bool值

  void _handleTapboxChanged(bool newValue) {//更改tapboxC激活状态时回调的函数
    setState(() {
      _active = newValue;
    });
  }

  @override
  Widget build(BuildContext context) {//父类widget的build函数:生成一个容器,里面有一个tapboxC,该盒子的active用父类的_active初始化(false)
    print("_parentWidgetCState Build");  //onChanged属性指明为父类中的_handleTapboxChanged,即盒子的active是由父类控制的    
    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();
}
//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, ), ), ); } }

 

posted @ 2020-07-22 21:10  NeoZy  阅读(461)  评论(0编辑  收藏  举报