Flutter性能优化之局部刷新

作者: 刺客的幻影 | 来源:发表于2019-07-28 16:29 被阅读0次

    Flutter中Widget分为StatefulWidget和StatelessWidget,分别为动态视图和静态视图,视图的更新需要调用StatefulWidget的setState方法,这会遍历调用子Widget的build方法。当一个主页面比较复杂时,会包含多个widget,如果直接调用setState,会遍历所有子Widget的build,这是非常不必要的性能开销,有没有单独刷新指定Widget的方式呢?这个时候就要用到GlobalKey了。

    常规刷新Widget的方法

    一个StatefulWidget包含一个Button,一个Text,通过点击Button调用主Widget的setState方法,刷新Text,示例如下:


    3041564298371_.pic_hd.jpg
    import 'package:flutter/material.dart';
    
    class TestWidget extends StatefulWidget {
      @override
      State<StatefulWidget> createState() {
        return _TestWidgetState();
      }
    }
    
    class _TestWidgetState extends State<TestWidget> {
      int _count;
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: Column(
            children: <Widget>[
              Text((_count++).toString()),
              RaisedButton(
                onPressed: () {
                  setState(() {
                    _count++;
                  });
                },
              )
            ],
          ),
        );
      }
    }
    

    通过GlobalKey局部刷新

    同样一个StatefulWidget包含一个多个Text和Button,点击Button我们只需要刷新指定的Text,通过GlobalKey的方式,实现如下:


    3051564298949_.pic_hd.jpg

    主Widget,包含一个需要更新的TextWidget和一个不需要更新的Text

    import 'package:cell_input/globalkey/button.dart';
    import 'package:cell_input/globalkey/text.dart';
    import 'package:flutter/material.dart';
    
    class TestWidget extends StatefulWidget {
      @override
      State<StatefulWidget> createState() {
        return _TestWidgetState();
      }
    }
    class _TestWidgetState extends State<TestWidget> {
      int _count=0;
      GlobalKey<TextWidgetState> textKey = GlobalKey();
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              TextWidget(textKey),///需要更新的Text
              SizedBox(height: 20,),
    
              Text(_count.toString(),style: TextStyle(fontSize: 20),), ///这个Text不会刷新,只会刷新上面的TextWidget
             SizedBox(height: 20,),
              ButtonWidget(
                onPressed: () {
                  ///点击button,调用TextWidget的onPressed方法
                  ///在TextWidget的onPressed中单独调用TextWidget的setState,
                  _count++;
                  textKey.currentState.onPressed(_count);
                },
              )
            ],
          ),
        );
      }
    }
    
    

    需要单独更新的Widget

    import 'package:flutter/material.dart';
    
    class TextWidget extends StatefulWidget {
      TextWidget(Key key) : super(key: key);
    
      @override
      State<StatefulWidget> createState() {
        return TextWidgetState();
      }
    }
    
    class TextWidgetState extends State<TextWidget> {
      String _text="0";
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: Text(_text,style: TextStyle(fontSize: 20),),
        );
      }
    
      void onPressed(int count) {
        setState(() {
          _text = count.toString();
        });
      }
    }
    
    

    传递事件的Button

    import 'package:cell_input/globalkey/text.dart';
    import 'package:flutter/material.dart';
    
    typedef OnPressed();
    
    class ButtonWidget extends StatefulWidget {
      OnPressed onPressed;
    
      ButtonWidget({this.onPressed});
    
      @override
      State<StatefulWidget> createState() {
        return _ButtonWidgetState(onPressed);
      }
    }
    
    class _ButtonWidgetState extends State<ButtonWidget> {
      OnPressed _onPressed;
    
      _ButtonWidgetState(this._onPressed);
    
      GlobalKey<TextWidgetState> key = GlobalKey();
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: RaisedButton(
            child: Text('count++',style: TextStyle(fontSize: 20),),
            onPressed: _onPressed,
          ),
        );
      }
    }
    
    

    这样点击Button就只会更新指定的TextWidget了,效果如下:


    gifhome_320x640_7s.gif

    这只是一个简单的例子,在实际开发中为了页面刷新的高效率,模块化封装非常重要。很多情况下都只需要局部刷新,而不是重构整个视图。所以Globalkey的运用在项目中需要熟练掌握
    demo地址:https://github.com/po1arbear/cell_input-flutter/tree/master/lib/globalkey

    相关文章

      网友评论

        本文标题:Flutter性能优化之局部刷新

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