美文网首页
Flutter UI代码优化

Flutter UI代码优化

作者: 简wen | 来源:发表于2021-03-25 17:17 被阅读0次

        Flutter发布到现在最让人吐槽的就是它的布局嵌套的写法,复杂布局嵌套层数多,导致代码阅读困难。其实如安卓与html语言布局代码也是嵌套的,不同的是它们把布局写到了单独的文件。
        本文分享一些避免Flutter的UI代码嵌套太深和优化代码的方式。如果对本文内容或观点有相关疑问,欢迎在评论中指出。

    一、最常见的嵌套布局优化,举个例子进行优化

    //优化前
    //左边一张图片,右边一些文本
    return Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Container(child: Image.asset("xxx.png"),width: 100,height: 100),
              Padding(
                padding: EdgeInsets.symmetric(horizontal: 10, vertical: 16),
                child: DefaultTextStyle(
                  style: TextStyle(color: Colors.pink, fontSize: 16),
                  child: Column(
                    children: [
                      Text("11111"),
                      Text("22222"),
                      Text("33333"),
                    ],
                  ),
                ),
              )
            ],
          );
    
    1. 拆分方法优化(注意:build ui方法嵌套不得超过2层,超过两层请抽成小组件类,或者用上面的方式优化)
    Widget build(BuildContext context) {
        return Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [_buildRight(),_buildLift()],
          //_buildLift() 后面写不写","很重要,写了会换行显示,开发中看代码长度决定
        );
      }
    
      _buildLift() => Container(child: Image.asset("xxx.png"), color: Colors.amber, width: 100, height: 100);
    
     _buildRight() {
        return Padding(
          padding: EdgeInsets.symmetric(horizontal: 10, vertical: 16),
          //_buildTexts()这边后面加了","换行显示更美观
          child: _buildTexts(),
        );
      }
    
      //已经到第二层了,如果还要抽成方法建议单独写组件
      _buildTexts() {
        DefaultTextStyle(
          style: TextStyle(color: Colors.pink, fontSize: 16),
          child: Column(children: [Text("11111"), Text("22222"), Text("33333")]),
        );
      }
    
    1. 使用局部变量优化(在Flutter源码中经常可以看的,如:Container())
    Widget build(BuildContext context) {
        return Scaffold(body: _buildItem());
      }
    
      _buildItem() {
        final left = Container(child: Image.asset("xxx.png"), width: 100, height: 100);
    
        Widget right = Column(children: [Text("11111"), Text("22222"), Text("33333")]);
        right = DefaultTextStyle(style: TextStyle(color: Colors.pink, fontSize: 16), child: right);
        right = Padding(padding: EdgeInsets.symmetric(horizontal: 10, vertical: 16), child: right);
        return Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [left, right],
        );
      }
    
    1. 使用扩展函数,这是我写的一个扩展函数库flu_ext
    Widget build(BuildContext context) {
        return Scaffold(
          body: Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Image.asset("xxx.png").container(width: 100, height: 100),
    
              Widgets.addWidget(Text("11111"))
                  .addWidget(Text("2222"))
                  .addWidget(Text("33333"))
                  .intoColumn()
                  .defaultTextStyle(style: TextStyle(color: Colors.pink, fontSize: 16))
                  .padding(padding: EdgeInsets.symmetric(horizontal: 10, vertical: 16)),
            ],
          ),
        );
    

    二、使用"...","if","for"优化,写布局难免会涉及到布局隐藏、动态添加等,举个例子进行优化

    //优化前
    //1.在一个listview里面显示一个banner
    //2.通过判断显示按钮
    //3.通过判断显示三个文本
    //4.显示三个icon
    //5.通过判断把String数组显示到界面上
    @override
      Widget build(BuildContext context) {
        bool isShowButton = false;
        bool isShowArr = true;
        const arr = ["第一个", "第二个", "第三个"];
    
        List<Widget> list = [
          //1.Banner
          _buildBanner(),
          //2.用三元符控制按钮显示与隐藏,会多渲染
          isShowButton ? FlatButton(onPressed: _onPressed, child: Text("按钮")) : SizedBox(),
        ];
        
        //3.用bool变量控制显示数组
        if (isShowArr) {
          list.addAll([Text("安卓"), Text("IOS"), Text("Flutter")]);
        }
        
        //4.添加数组
        list.addAll(_buildIcons());
    
        //5.用bool变量控制显示数组
        if (isShowArr) {
          list.addAll(arr.map((e) => Text(e)).toList());
        }
        return Scaffold(
          body: ListView(children: list),
        );
      }
    
      _buildBanner() => Container(height: 100, width: double.infinity, color: Colors.amberAccent);
    
      List<Widget> _buildIcons() {
        return [Icon(Icons.android, size: 30), Icon(Icons.home, size: 30), Icon(Icons.person_rounded, size: 30)];
      }
    

    优化后

    Widget build(BuildContext context) {
        bool isShowButton = false;
        bool isShowArr = true;
        const arr = ["第一个", "第二个", "第三个"];
        
        return Scaffold(
          body: ListView(
            children: [
              //1.Banner
              _buildBanner(),
              //2.用bool变量控制按钮显示与隐藏
              if (isShowButton) FlatButton(onPressed: _onPressed, child: Text("按钮")),
              //3.用bool变量控制显示数组,用...添加数组或集合
              if (isShowArr) ...[Text("安卓"), Text("IOS"), Text("Flutter")],
              //4.用...添加数组或集合
              ..._buildIcons(),
              //5.用bool变量控制显示数组,用for循环展示
              if (isShowArr)
                for (var value in arr) Text(value),
            ],
          ),
        );
      }
    
      _buildBanner() => Container(height: 100, width: double.infinity, color: Colors.amberAccent);
    
      List<Widget> _buildIcons() {
        return [Icon(Icons.android, size: 30), Icon(Icons.home, size: 30), Icon(Icons.person_rounded, size: 30)];
      }
    
      _onPressed() {}
    
    

    三、最后通过命名构造降低使用难度,适用于复用界面

    ///优化前
    ///一个游戏商店,有三个角色,vip,游戏管理员,普通用户(普通用户分有没有钱)
    ///创建vip界面
    GameStorePage(isVip: true);
    ///创建普通用户没钱界面
    GameStorePage(isVip: false);
    ///创建普通用户有钱界面
    GameStorePage(isVip: false,isHaveMoney: true);
    ///创建GM界面
    GameStorePage(isGM: true);
    ///这种创建方式需要使用者必须了解多种参数的组合
    
    class GameStorePage extends StatelessWidget {
      final bool isVip;
      final bool isHaveMoney;
      final bool isGM;
    
      //写const可以优化内存
      const GameStorePage({Key key, this.isVip = false, this.isHaveMoney = false, this.isGM = false})
          : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return ListView(
          children: [
            if (isVip || isGM) _buildVipUI(), //vip界面
            if (!isVip && !isGM) _buildNormalUI(), //普通用户界面
            if (isGM) _buildEditGoodsButton(), //GM可以编辑商品
            if (isVip || isHaveMoney) _buildPayButton(), //vip和有钱的用户可以直接支付
          ],
        );
      }
    //........代码省略
    }
    

    优化后

    ///一个游戏商店,有三个角色,vip,游戏管理员,普通用户(普通用户分有没有钱)
    ///创建vip界面
    GameStorePage.vip();
    ///创建普通用户没钱界面
    GameStorePage.normal();
    ///创建普通用户有钱界面
    GameStorePage.normal(isHaveMoney:true);
    ///创建GM界面
    GameStorePage.gm();
    ///这种创建方式屏蔽内部细节,使用简单
    class GameStorePage extends StatelessWidget {
      final bool isVip;
      final bool isHaveMoney;
      final bool isGM;
    
      //写const可以优化内存
      const GameStorePage.vip({Key key}):isGM=false,isHaveMoney=false,isVip=true,super(key: key);
      const GameStorePage.normal({Key key,this.isHaveMoney=false}):isGM=false,isVip=false,super(key: key);
      const GameStorePage.gm({Key key}):isGM=true,isHaveMoney=false,isVip=false,super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return ListView(
          children: [
            if (isVip || isGM) _buildVipUI(), //vip界面
            if (!isVip && !isGM) _buildNormalUI(), //普通用户界面
            if (isGM) _buildEditGoodsButton(), //GM可以编辑商品
            if (isVip || isHaveMoney) _buildPayButton(), //vip和有钱的用户可以直接支付
          ],
        );
      }
    //........代码省略
    }
    

    相关文章

      网友评论

          本文标题:Flutter UI代码优化

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