走进 “Flutter”

走进 “Flutter”_第1张图片
flutter.jpg

如何安装 Flutter 请点击这里

1、Flutter 是什么?

Flutter是一款移动应用程序SDK,包含框架、widget和工具,为开发人员提供了一种在Android和iOS上构建和部署精美移动应用程序的简单高效的方式。

2、Flutter 优点与缺点

优点

1、性能强大、流畅

  • Flutter 对比 weex 和 react native ,性能强大是有目共睹的,因为基于 dom 树渲染原生组件,很难与原生视图绘图比性能, Google 直接在两个平台上重写了各自的 UIKit, 直接对接平台底层,减少 UI 层的多层转换,让 UI 的性能几乎可以比肩原生,在列表的滑动体验最为明显。

2、热重载

简单的来说就是 比如我们改变了一些代码(例如文本变了),点击 “热重载” 或者 保存文件,能在很短的时间内看到结果,这样体验是不是更好?

3、UI稳定

因为 Google 重写了 UIKit,不依赖 Css 解释器,不会存在 UI 渲染不正常的情况,让 UI 的效果表现的更加稳定。

4、万物皆 Widget

Flutter 的核心原则 —— 所有东西都是一个小部件。你的 app 类是一个小部件(MaterialApp),你的整体布局结构也是一个小部件(Scaffold),所有东西都是一个小部件(AppBar, Drawer, SnackBar)。

有了 Fluter,创建 UI 就像用许多不同的小部件组合布局一样简单。

Flutter 还有另外一个核心原则,组合优先于继承。这意味着,如果你想要创建一些新的部件(widget),则可以使用几个 Widget 组成新的 Widget ,而不是扩展现有的 Widget 类。

缺点

1、假装跨平台,躲不开原生代码

这是最大的问题,跨平台框架说白了就是UI跨平台,最后还是在原生平台运行,本来两个平台就有天壤之别,一套代码就想吃掉iOS和Android在实际应用之中其实根本就不现实。Flutter具有与原生代码互相调用的能力固然非常科学,但是问题反而显得更加明显——我一个前端工程师上哪里去知道什么是UIViewController,什么是Activity呢?我要是双端都熟悉,学习Flutter就显得很没有必要。这是一个很矛盾的点,特别是在团队里,只有几个前端突然想学Flutter,是绝对做不来大项目的,如果有原生开发者,那就没必要搞Flutter了。

2、资源管理不方便

Flutter 支持不同分辨率的图片,但是目录设计不合理,图片不能直接拖到 Flutter 用,这点设计让我们使用起来极其麻烦。

3、Widget 的类型初建项目难以抉择

Flutter的Widget分为StatefulWidget和StatelessWidget两种,一种是带状态的一种是不带状态的,刚开发的时候很难想明白用哪个,因为StatelessWidget也能存值,其实区别就在于框架重构UI的时候会使用State来重构,如果是StatelessWidget,暂时存进去的值就没了。

4、需要梯子,因为有墙。

因为中国国情,想更好的开发 Flutter 需要有梯子,否则难度系数有点高。

3、为什么Flutter选择使用Dart语言?

Flutter在四个主要维度进行了评估,并考虑了框架作者、开发人员和最终用户的需求等因素。我们发现不同的语言在不同的层面符合一部分需求,但Dart在所有评估维度上得分都很高,并且符合我们的所有要求和标准。

Dart运行时和编译器支持Flutter的两个关键特性的组合:基于JIT的快速开发周期:允许使用类型的语言进行形状更改和有状态的热重载;以及AOT编译器,可生成高效的ARM代码,可以快速启动并拥有可预测的生产部署性能。

此外,我们有机会与Dart社区密切合作,Dart社区正在积极投入资源改进Dart在Flutter中的使用。例如,当我们采用Dart时,该语言没有提供生成原生二进制文件的工具链(这对于实现可预测的高性能是很有帮助的),但是现在实现了,因为Dart团队为Flutter构建了它。同样,Dart VM之前已经针对吞吐量进行了优化,但团队现在正在优化VM的延迟时间,这对于Flutter的工作负载更为重要。

Dart在以下主要标准上得到高分:

开发人员的效率。Flutter的主要价值主张之一是通过让开发人员使用相同的代码库为iOS和Android创建应用程序,从而节省了工程资源。使用高效的语言可以进一步加速开发周期,并使Flutter更具吸引力。这对我们的framework团队和开发人员都非常重要。大部分Flutter功能都是用Dart实现,因此我们需要在10万行代码时能保持高效的而不会牺牲framework和widget的可读性。

面向对象。虽然我们可以使用非面向对象的语言,但这意味着要重新解决几个难题。另外,绝大多数开发人员都具有面向对象开发的经验,因此更容易学习如何使用Flutter进行开发。

可预测,高性能。借助Flutter,我们希望使开发人员能够快速创建流畅的用户体验。为了实现这一点,我们需要能够在每个动画帧中运行大量的代码。这意味着我们需要一种既能提供高性能又能提供可预测性能的语言,而不会出现会导致丢帧的周期性暂停。

快速内存分配。Flutter框架使用函数式流,它很大程度上依赖于底层的内存分配器,从而有效地处理小的、短期的内存分配会非常重要,所以在缺乏此功能的语言中Flutter无法有效地工作。

4、快速了解 Flutter 上手更容易

走进 “Flutter”_第2张图片
image.png

从上图我们能够看出 Flutter 的核心设计围绕着 Widget 的。

1、组件

  • Text

Text 是UI开发的最重要的组件之一,文字展示都要靠 Text 组件来完成,
Flutter的 Text组件 属性很丰富。

const Text(this.data, {
  Key key,
   this.style,  //风格样式,没设置的话默认使用 DefaultTextStyle
   this.textAlign,   //文本水平如何对齐
   this.textDirection,  //方向性
   this.locale,   
   this.softWrap, // 文本是否换行符换行,如何为false,那么文本就会一直水平显示
   this.overflow, // 处理文本溢出的视觉效果
   this.textScaleFactor, //字体像素数  
   this.maxLines, //可选的文本最大行数,必要时进行换行。
   this.semanticsLabel, //语义标签
}) : assert(data != null),
     textSpan = null,
     super(key: key);
  • Image

 const Image({
   Key key,
   @required this.image,
   this.semanticLabel, //图像的语义描述
   this.excludeFromSemantics = false, //是否从语义中删除该图像。
   this.width, //宽度
   this.height, //高度
   this.color, // 颜色
   this.colorBlendMode, // 让颜色和图混合在一起
   this.fit, // 如何将图像显示。有以下几种模式 fill 、contain、cover、fitWidth、fitHeight、none、scaleDown
   this.alignment = Alignment.center, // 图片的边界内对齐。
   this.repeat = ImageRepeat.noRepeat, // 绘制没有被图片覆盖的部分
   this.centerSlice,  //图像中心切片内的区域将同时被拉伸
   this.matchTextDirection = false, //是否按照 TextDirection 的方向绘制图了
   this.gaplessPlayback = false,  //是继续显示旧图片,还是不显示 (图片被修改时)
   this.filterQuality = FilterQuality.low,  //设置质量
 }) : assert(image != null),
      assert(alignment != null),
      assert(repeat != null),
      assert(filterQuality != null),
      assert(matchTextDirection != null),
      super(key: key);
  • Container(容器)

Container 本身是一个widget。但是他却提供了对基础widget的封装,提高了UI基础装饰能力的表达效率。

Container({
   Key key,
   this.alignment,  // 容器内对齐
   this.padding,  //设置内边距属性,内边距的空白区域  示例 new EdgeInsets.all(8.0),
   Color color,  //颜色
   Decoration decoration, // 一般实际场景中会使用他的子类BoxDecoration。BoxDecoration提供了对背景色,边框,圆角,阴影和渐变等功能的定制能力。
   this.foregroundDecoration, // decoration 要设置在  child 前面
   double width, //宽
   double height, // 高
   BoxConstraints constraints, //约束 
   this.margin,  // decoration 与 child 的空间
   this.transform,  //  decoration 转换
   this.child,  // 容器内的元素 例如 Text('我是谁'),
 }) 
  • GestureDetector(手势)

使用时只需要将GestureDetector包裹在目标widget外面,再实现对应事件的函数即可。从点击到长按,从缩放到拖动,这个类基本上都有相应的实现。

GestureDetector({
   Key key,
   this.child,
   this.onTapDown,
   this.onTapUp,
   this.onTap,
   this.onTapCancel,
   this.onDoubleTap,
   this.onLongPress,
   this.onLongPressUp,
   this.onVerticalDragDown,
   this.onVerticalDragStart,
   this.onVerticalDragUpdate,
   this.onVerticalDragEnd,
   this.onVerticalDragCancel,
   this.onHorizontalDragDown,
   this.onHorizontalDragStart,
   this.onHorizontalDragUpdate,
   this.onHorizontalDragEnd,
   this.onHorizontalDragCancel,
   this.onForcePressStart,
   this.onForcePressPeak,
   this.onForcePressUpdate,
   this.onForcePressEnd,
   this.onPanDown,
   this.onPanStart,
   this.onPanUpdate,
   this.onPanEnd,
   this.onPanCancel,
   this.onScaleStart,
   this.onScaleUpdate,
   this.onScaleEnd,
   this.behavior,
   this.excludeFromSemantics = false
 })

2、布局

Flutter布局分为:

  • SingleChildRenderObjectWidget
    1、 center
    2、padding
    3、container

  • MultiChildRenderObjectWidget
    1、stack
    2、flex
    3、flow

  • Flex

走进 “Flutter”_第3张图片
Flex.png

上面的是 flex 布局概念

flex通过direction设置了flex的主轴方向即main axis。
和主轴垂直的方向叫做cross axis。
flex布局中对子布局的控制是从main axis 和cross axis两个方向上进行的。
例如居中有main axis居中和cross axis居中。两者都居中才是容器的完全居中。

crossAxisAlignment、mainAxisAlignment 和 Column 、Row 一起使用更爽

走进 “Flutter”_第4张图片
Column.png
Row.png
  • Stack (实现层式布局)

开发过程中,我们通常需要在一些 Widgets 的上面再覆盖上新的 Widgets 。
我们就用到了 Stack

  • positioned 可以通过Positioned属性灵活定位
  • non-positioned 通过父Widget Stack 的属性来控制布局

对于non-positioned children, 我们通过控制Stack的alignment属性来控制对齐方式。
Positioned的布局方式类似于H5&weex中的position布局中的absolute布局方式。
通过设置距离父组件上下左右的距离,Positioned对象能在Stack布局中更加灵活的控制view的展现方式。

组件隐藏
  • 父容器的list中 删除要隐藏的cell
  • offstage 属性设置为 true ,在Offstage 上面的 child 包括它本身都不会被绘制。
  • 使用透明度(不建议使用)

3、生命周期

  • Stack 生命周期

didChangeDependencies state依赖的对象发生变化时调用

名称 状态
initState 插入渲染树时调用,只调用一次
didChangeDependencies state依赖的对象发生变化时调用
didUpdateWidget 组件状态改变时候调用,可能会调用多次
build 构建Widget时调用
deactivate 当移除渲染树的时候调用
dispose 组件即将销毁时调用
走进 “Flutter”_第5张图片
state 生命周期.png

注意

这里的状态改变包括两种可能:
1.通过setState内容改变
2.父节点的state状态改变,导致子节点的同步变化。

  • StatelessWidget 和 StatefulWidget的区别

StatelessWidget是状态不可变的widget。初始状态设置以后就不可再变化。如果需要变化需要重新创建。
StatefulWidget可以保存自己的状态。
那问题是既然widget都是immutable的,怎么保存状态?
其实Flutter是通过引入了State来保存状态。当State的状态改变时,能重新构建本节点以及child的Widget树来进行UI变化。
注意:如果需要主动改变State的状态,需要通过setState()方法进行触发,单纯改变数据是不会引发UI改变的。

  • 内存问题

目前发现的问题:大量的push 加载 图片会造成内存暴涨导致闪退,

原因:是 Flutter 的加载机制,如果不进行任何处理, 每次加载图片,不管有没有渲染到界面上的图片都会去加载,所以频繁刷页面会造成内存峰值过高,关于 widgets 官方介绍点击这里

解决:在页面不可见的时候不发出多余的图片加载请求。

内存调试工具 Xcode Instruments

部分内容借鉴引用咸鱼技术

你可能感兴趣的:(走进 “Flutter”)