谈谈我对 Flutter 发展前景 和 “嵌套地狱” 的浅显看法

时间:2022-07-24
本文章向大家介绍谈谈我对 Flutter 发展前景 和 “嵌套地狱” 的浅显看法,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

历史上的今天

郑成功(1624.08.26-1662.06.23),本名森,又名福松,字明俨、大木。福建泉州南安人,祖籍河南固始。汉族,明末清初军事家,抗清名将,民族英雄。其父郑芝龙,其母名田川氏。弘光时监生,因蒙隆武帝赐明朝国姓“朱”,赐名成功,并封忠孝伯,世称“郑赐姓”、“郑国姓”、“国姓爷”,又因蒙永历帝封延平王,称“郑延平”。

1645年(清顺治二年,弘光元年)清军攻入江南,不久郑芝龙降清、田川氏在乱军中自尽;郑成功率领父亲旧部在中国东南沿海抗清,成为南明后期主要军事力量之一,一度由海路突袭、包围清江宁府(原明朝南京),但终遭清军击退,只能凭借海战优势固守泉州府的海岛厦门、金门。1661年(清顺治十八年,永历十五年)率军横渡台湾海峡,翌年击败荷兰东印度公司在台湾大员(今台湾台南市境内)的驻军,收复台湾,开启郑氏在台湾的统治 。

正文

Flutter 发展前景

提到 Flutter 就不得不提到 Fuchsia 系统,这是一个尚未正式发布的操作的系统,引用 Android 和 Chrome 的高级副总裁 Hiroshi Lockheimer 在一档播客节目中对 Fuchsia 的介绍是:

不仅仅是手机和个人电脑,在物联网的世界里,越来越多的设备需要操作系统、新的软件运行环境等支持。我认为,在具有不同优势和专业化的诸多操作系统中还存在很大的发展空间。Fuchsia 就是其中之一,所以,请继续保持关注。

是的,Fuchsia 系统是为物联网研发的操作系统,物联网简称 IoT

那 Flutter 和 Fuchsia 又是什么关系呢?

Flutter 是 Fuchsia 官方指定的唯一UI开发语言。

目前市面上有很多物联网操作系统 ,Fuchsia 就一定可以脱颖而出吗?

未来的事谁说的准呢,这里引用 Google 公众号底部的一句话送给大家:

预测未来不如创造未来

在跨平台技术上 Flutter 还有很多竞争对手,比如 HTML5、React Native、Weex、快应用、小程序等,在【Flutter实战】移动技术发展史 中详细说明了各个跨平台技术的发展历史及优缺点。

Flutter 的出现会终结其他跨平台技术?我想不会的, React Native 发展了这么多年也没有完全干掉 HTML5,因为 HTML5 有其独特的应用场景,比如 营销活动场景、新闻或者博客详情页面等,这些场景非常适合 HTML5。因此 Flutter 也不可能终结其他跨平台技术,总结一句话就是:

未来很长一段时间,将会是跨平台技术共存的时代,但 Flutter 适用场景更为广阔。

Flutter 嵌套地狱

现在网络上对 Flutter 吐槽最多大概就是 Flutter “嵌套地狱”写法了,为什么会出现这种现象?个人认为最大的原因就是目前大部分开源的 Flutter 项目都是这种嵌套写法(包括我自己以前也是如此),导致后来的初学者认为这样写没有问题,当项目越来越复杂时,这种嵌套写法给项目的维护带来了巨大的挑战。

比如实现如下效果:

嵌套地狱 的写法:

@override
Widget build(BuildContext context) {
  return Column(
    children: <Widget>[
      Container(
        height: 45,
        child: Row(
          children: <Widget>[
            SizedBox(
              width: 30,
            ),
            Icon(
              Icons.notifications,
              color: Colors.blue,
            ),
            SizedBox(
              width: 30,
            ),
            Expanded(
              child: Text('消息中心'),
            ),
            Container(
              padding: EdgeInsets.symmetric(horizontal: 10),
              decoration: BoxDecoration(
                  shape: BoxShape.rectangle,
                  borderRadius: BorderRadius.all(Radius.circular(50)),
                  color: Colors.red),
              child: Text(
                '2',
                style: TextStyle(color: Colors.white),
              ),
            ),
            SizedBox(
              width: 15,
            ),
          ],
        ),
      ),
      Divider(),
      //类似上面的布局写6个
    ],
  );
}

上面还仅仅是第一项的布局,下面还有7个,一个30多行代码,7个就是200多行的布局代码,这还仅仅是布局代码,如果加上逻辑,都不敢想象啊。

有一点封装思想开发者都会将每一个 Item封装一下,写法如下:

_buildItem(IconData iconData, Color iconColor, String title, Widget widget) {
  return Container(
    height: 45,
    child: Row(
      children: <Widget>[
        SizedBox(
          width: 30,
        ),
        Icon(
          iconData,
          color: iconColor,
        ),
        SizedBox(
          width: 30,
        ),
        Expanded(
          child: Text('$title'),
        ),
        widget,
        SizedBox(
          width: 15,
        ),
      ],
    ),
  );
}

@override
Widget build(BuildContext context) {
  return Column(
    children: <Widget>[
      _buildItem(...),
      Divider(),
      _buildItem(...),
      Divider(),
      _buildItem(...),
      Divider(),
      _buildItem(...),
      Divider(),
      _buildItem(...),
      Divider(),
      _buildItem(...),
      Divider(),
    ],
  );
}

这样看起来好多了,基本解决了嵌套地狱问题,但这样写还存在一个非常大的问题-性能问题,一旦其中一个数字发生变化,整个页面都要重建,Flutter 开发中非常重要的一个原则就是 尽可能少重建组件,因此将上面封装方法中组件变为一个单独的 Widget。

class SettingDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        _SettingItem(
          iconData: Icons.notifications,
          iconColor: Colors.blue,
          title: '消息中心',
          suffix: _NotificationsText(
            text: '2',
          ),
        ),
        Divider(),
        _SettingItem(
          iconData: Icons.thumb_up,
          iconColor: Colors.green,
          title: '我赞过的',
          suffix: _Suffix(
            text: '121篇',
          ),
        ),
        Divider(),
        _SettingItem(
          iconData: Icons.grade,
          iconColor: Colors.yellow,
          title: '收藏集',
          suffix: _Suffix(
            text: '2个',
          ),
        ),
        Divider(),
        _SettingItem(
          iconData: Icons.shopping_basket,
          iconColor: Colors.yellow,
          title: '已购小册',
          suffix: _Suffix(
            text: '100个',
          ),
        ),
        Divider(),
        _SettingItem(
          iconData: Icons.account_balance_wallet,
          iconColor: Colors.blue,
          title: '我的钱包',
          suffix: _Suffix(
            text: '10万',
          ),
        ),
        Divider(),
        _SettingItem(
          iconData: Icons.location_on,
          iconColor: Colors.grey,
          title: '阅读过的文章',
          suffix: _Suffix(
            text: '1034篇',
          ),
        ),
        Divider(),
        _SettingItem(
          iconData: Icons.local_offer,
          iconColor: Colors.grey,
          title: '标签管理',
          suffix: _Suffix(
            text: '27个',
          ),
        ),
      ],
    );
  }
}

class _SettingItem extends StatelessWidget {
  const _SettingItem(
      {Key key, this.iconData, this.iconColor, this.title, this.suffix})
      : super(key: key);

  final IconData iconData;
  final Color iconColor;
  final String title;
  final Widget suffix;

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 45,
      child: Row(
        children: <Widget>[
          SizedBox(
            width: 30,
          ),
          Icon(iconData,color: iconColor,),
          SizedBox(
            width: 30,
          ),
          Expanded(
            child: Text('$title'),
          ),
          suffix,
          SizedBox(
            width: 15,
          ),
        ],
      ),
    );
  }
}

class _NotificationsText extends StatelessWidget {
  final String text;

  const _NotificationsText({Key key, this.text}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.symmetric(horizontal: 10),
      decoration: BoxDecoration(
          shape: BoxShape.rectangle,
          borderRadius: BorderRadius.all(Radius.circular(50)),
          color: Colors.red),
      child: Text(
        '$text',
        style: TextStyle(color: Colors.white),
      ),
    );
  }
}

class _Suffix extends StatelessWidget {
  final String text;

  const _Suffix({Key key, this.text}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Text(
      '$text',
      style: TextStyle(color: Colors.grey.withOpacity(.5)),
    );
  }
}

封装为一个个单独的小组件,将有变化的组件尽量单独封装,这样就不会重建整个控件树,增强了可读性和可维护性,而且对性能有很大的提升。

最后总结一句:

虽然 Flutter 一切皆是组件,但并不代表一切都要写在一个组件中。

当然这仅仅是我个人的看法,如果您有更好的方法欢迎一起讨论,从我做起,规范写法,为 Flutter 发展贡献做出一点微不足道的贡献。