Flutter之HolleWold

Flutter 第一个项目是一个计数器

Flutter 的Dart代码是写在lib 文件夹下,而 lib/main.dart 是项目的入口,打开main.dart ,下边是代码:

//引入material UI库,可以理解为iOS的UIKit
import 'package:flutter/material.dart';

// 传说中的main 函数,使用dart 的特有的  => 调用方法
// 调用了MyApp函数
void main() => runApp(new MyApp());

// Widget(部件),可以理解为iOS中的UIView,iOS中叫控件,都由view封装而成,Flutter中都叫部件(小部件),都由widget封装而成
// extends:继承(OC不这么写,因为OC 一个类有2个文件组成 .h和.m)--OC 是最NB的[偷笑]!
class MyApp extends StatelessWidget {
  //重写 build 方法(描述如何构建UI界面)
  @override
  Widget build(BuildContext context) {
  // MaterialApp :是Material库中提供的Flutter APP框架,通过它可以设置应用的名称、主题、语言、首页及路由列表等
    return new MaterialApp(
 //名称
      title: 'Flutter Demo',
//主题
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
//应用首页路由 
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
//首页
class MyHomePage extends StatefulWidget {
//可选参数,首页导航标题,如果不清楚可以
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
// 加载首页的状态类,StatefulWidget 的特殊写法,下边详细介绍
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}
// State 状态
// <MyHomePage> 这这个类的状态
class _MyHomePageState extends State<MyHomePage> {
//记录计数器的数字
  int _counter = 0;
// 点击 “+” 按钮调用的方法,实现 i++
// _incrementCounter 这种下划线的命名的方法,表示是一个私有方法
  void _incrementCounter() {
// 刷新页面
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
// Scaffold :是Material库中提供的页面脚手架,它包含导航栏和Body以及FloatingActionButton
// 就是一个封装了导航栏等等功能的小部件,可以简单理解为UINavgation
    return new Scaffold(
// 导航栏
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
// Center : 一个空白的view (web 中的 div )
      body: new Center(
// Column: 一种布局方案,下一章布局详细介绍 
        child: new Column(
// 布局中的对齐,居中
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
// lab
            new Text(
              'You have pushed the button this many times:',
            ),
            new Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
// 按钮
      floatingActionButton: new FloatingActionButton(
        onPressed: _incrementCounter,// 调用方法
        tooltip: 'Increment',
        child: new Icon(Icons.add),// icon
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

代码还是比较简单的,点击按钮,调用 _incrementCounter 方法,_counter++,刷新页面,让 Text 显示

接下来,详细介绍一下,里边包含的知识点:

StatelessWidget 和 StatefulWidget

StatelessWidget: 无状态Widget,一旦创建,不能改变
StatefulWidget: 有状态的Widget,可以根据状态改变

  1. StatefulWidget 其实就是 StatelessWidget + 状态组成
  2. 其实 StatefulWidget 能够改变,也只是保存了“状态”,删除了老的StatelessWidget,重新创建了一个新的
  3. 所以StatelessWidget 是一个方法,而StatefulWidget 要多写一个 State 方法

刷新页面 setState

// 下边2种写法都可以
_counter++;
setState(() {});

setState(() {
      _counter++;
});
  1. 调用刷新页面,删除了老的StatelessWidget,新建一个StatelessWidget,重新展示改变状态以后的页面
  2. 代码逻辑其实重新执行build 方法,来重绘,所以build 方法里边只放和页面布局相关的东西,不要放逻辑代码

widget 底层

widget 继承DiagnosticableTree,主要的包括key,Element ,canUpdate等等。

  1. key:这个key属性类似于React/Vue中的key,主要的作用是决定是否在下一次build时复用旧的widget,决定的条件在canUpdate()方法中。
  2. canUpdate:是否用新的Widget对象去更新旧UI树上所对应的Element对象的配置;只要newWidget与oldWidget的runtimeType和key同时相等时就会用newWidget去更新Element对象的配置,否则就会创建新的Element。
  3. Element属性

事实上 Widget 只是 Element 的一个配置描述 ,告诉 Element 这个实例如何去渲染。
从上图注释也可知: Widget 和 Element 之间是一对多的关系 。

而Element 里边有renderObject属性

而renderObject 是Flutter布局和绘制的基本单元

由此可以得出: Widget 生成了 Element,而后创建 RenderObject 关联到 Element 的内部 renderObject 对象上,最后Flutter 通过 RenderObject 数据来布局和绘制。

说到 RenderObject ,就不得不说 RenderBox ,从源码注释可以看出,它是在继承 RenderObject 基础的布局和绘制功能上,实现了“笛卡尔坐标系”:以 Top、Left 为基点,通过宽高两个轴实现布局和嵌套的。

RenderBox 避免了直接使用 RenderObject 的麻烦场景,其中 RenderBox 的布局和计算大小是在 performLayout() 和 performResize() 这两个方法中去处理,很多时候我们更多的是选择继承 RenderBox 去实现自定义。

综合上述情况,我们知道:

  1. Widget只是显示的数据配置,所以相对而言是轻量级的存在,而 Flutter 中对 Widget 的也做了一定的优化,所以每次改变状态导致的 Widget 重构并不会有太大的问题。
  2. RenderObject 就不同了,RenderObject 涉及到布局、计算、绘制等流程,要是每次都全部重新创建开销就比较大了。

所以针对是否每次都需要创建出新的 Element 和 RenderObject 对象,Widget 都做了对应的判断以便于复用,比如:在 newWidget 与oldWidget 的 runtimeType 和 key 相等时会选择使用 newWidget 去更新已经存在的 Element 对象,不然就选择重新创建新的 Element。

由此可知:Widget 重新创建,Element 树和 RenderObject 树并不会完全重新创建。

那么再来个图理解一下:

widget 底层这块参考大神所写:
https://juejin.im/post/5c7e853151882549664b0543

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349