Flutter入门 - 初识

Flutter入门篇

初识

Flutter 是 Google推出并开源的移动应用开发框架,主打跨平台、高保真、高性能。使用Skia绘制引擎实现自绘UI系统,实现自绘UI+原生的跨平台框架,目前已默认支持iOS、Android、Fuchsia(Google新的自研操作系统)三个移动平台,还有Web开发(Flutter for web)和PC开发。
高性能主要靠两点来保证,首先,Flutter采用Dart语言开发。Dart是为数不多同时支持JIT和AOT的语言。在开发阶段,Dart在 JIT(即时编译)模式下,速度与 JavaScript基本持平。 Dart在发布期使用 AOT,当以 AOT模式运行时,JavaScript便远远追不上了。速度的提升对高帧率下的视图数据计算很有帮助。其次,Flutter使用自己的渲染引擎来绘制UI,布局数据等由Dart语言直接控制,所以在布局过程中不需要像RN那样要在JavaScript和Native之间通信,这在一些滑动和拖动的场景下具有明显优势,因为在滑动和拖动过程往往都会引起布局发生变化,所以JavaScript需要和Native之间不停的同步布局信息,这和在浏览器中要JavaScript频繁操作DOM所带来的问题是相同的,都会带来比较可观的性能开销。

框架结构

在这里插入图片描述

Embedder:作为在不同平台下与底层系统协调获取服务的针对各平台入口。利用此底层嵌入器,flutter可以将code作为module嵌入原生app,也可作为完整app跨平台使用。
Engine:纯 C++实现的 SDK,其中包括了 Skia引擎、Dart运行时、文字排版引擎等。通过dart:ui包暴露classes
FrameWork:纯 Dart实现的 SDK,提供一套基础库。
从下往上支持:

  • Foundation和Animation、Painting、Gestures在Google的一些视频中被合并为一个dart UI层,对应的是Flutter中的dart:ui包,它是Flutter引擎暴露的底层UI库,提供动画、手势及绘制能力。
  • Rendering 抽象的布局层,它依赖于dart UI层,Rendering层会构建一个UI树,当UI树有变化时,会计算出有变化的部分,然后更新UI树,最终将UI树绘制到屏幕上,这个过程类似于React中的虚拟DOM。Rendering层可以说是Flutter UI框架最核心的部分,它除了确定每个UI元素的位置、大小之外还要进行坐标变换、绘制(调用底层dart:ui)。
  • Widgets层是Flutter提供的的一套基础组件库,在基础组件库之上,Flutter还提供了 Material 和Cupertino两种视觉风格的组件库。而我们Flutter开发的大多数场景,只是和这两层打交道

demo

从项目结构上看,创建project默认支持ios和android平台,同时引入需要的libraries
项目代码路径位于…/lib下,程序入口为Flutter的入口在"lib/main.dart"的main()函数
在这里插入图片描述

认识demo

void main() {
  runApp(MyApp());//flutter入口
}

class MyApp extends StatelessWidget {
  // 作为应用的根组件
  @override
  Widget build(BuildContext context) {
    return MaterialApp( //应用使用material主题框架
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        // This makes the visual density adapt to the platform that you run
        // the app on. For desktop platforms, the controls will be smaller and
        // closer together (more dense) than on mobile platforms.
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: HomePage(),//主页widget构建显示
    );
  }
}

//statefuleWidget由widget类和对应state类实现
class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);//widget构造函数
   //Key作为重要元素,当前仅理解与rebuild对比相关,在组件树中有唯一性
  
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

//dart语言以"_"开头表示private
class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {//变动后,需引发rebuild的导火线
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(//脚手架
      appBar: AppBar(
        title: Text(widget.title),//state类直接拥有相关widget类对象
      ),
      body: Center(//layout widget
        child: Column(//layout widget
          mainAxisAlignment: MainAxisAlignment.center,//对齐方式
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',//变量使用
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,//按钮响应函数
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), 
    );
  }
}

Widget

我们知道在Flutter中几乎所有的对象都是一个Widget。与原生开发中“控件”不同的是,Flutter中的Widget的概念更广泛,它不仅可以表示UI元素,也可以表示一些功能性的组件如:用于手势检测的 GestureDetector widget、用于APP主题数据传递的Theme等等。

Widget作为控件大致分为StatelessWidget和StatefulWidget。

StatelessWidget内部直接使用build方法构造显示元素

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: new Container(
        color: Colors.white,
        child: new Text("hello world"),
      ),
    );
  }
}

StatefulWidget试例由demo可见,通过setState()引发页面改动部分重新渲染。
StatefulWidget状态管理用法:

class ClickPage extends StatelessWidget {
  final String title = 'clickPage';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(title),
        ),
        body: Center(
          child: ParentWidgetC(),
        ));
  }
}//页面快速构建

class ParentWidgetC extends StatefulWidget {
  @override
  _ParentWidgetCState createState() => new _ParentWidgetCState();
}

class _ParentWidgetCState extends State<ParentWidgetC> {
  bool _active = false;

  void _handleTapboxChanged(bool newValue) {
    setState(() {
      _active = newValue;
    });
  }

  @override
  Widget build(BuildContext context) {
    print("mt ParentWidgetC build");
    return new Container(
      child: new Tapbox(
        active: _active,//父Widget管理变量改动
        onChanged: _handleTapboxChanged, //函数作为参数传入
      ),
    );
  }
}
----------------------------子widget构建---------------------------------
  
class Tapbox extends StatefulWidget {
  Tapbox({Key key, this.active: false, @required this.onChanged})
      : super(key: key);

  final bool active;//父Widget管理的状态变量,由子Widget渲染具体内容
  final ValueChanged<bool> onChanged;//回调引发父Widget rebuild

  @override
  _TapboxState createState() => new _TapboxState();
}

class _TapboxState extends State<Tapbox> {
  bool _highlight = false;//子Widget控制触碰边框的状态变量

  void _handleTapDown(TapDownDetails details) {
    setState(() {
      _highlight = true;
    });
  }

  void _handleTapUp(TapUpDetails details) {
    setState(() {
      _highlight = false;
    });
  }

  void _handleTapCancel() {
    setState(() {
      _highlight = false;
    });
  }

  void _handleTap() {
    widget.onChanged(!widget.active);
  }

  @override
  Widget build(BuildContext context) {
    print("mt Tapbox build");
    // 在按下时添加绿色边框,当抬起时,取消高亮
    return new GestureDetector(//手势事件也可设定区域作为widget
      onTapDown: _handleTapDown,
      onTapUp: _handleTapUp,
      onTap: _handleTap,
      onTapCancel: _handleTapCancel,
      child: new Container(
        child: new Center(
          child: new Text(widget.active ? 'Active' : 'Inactive',
              style: new TextStyle(fontSize: 32.0, color: Colors.white)),
        ),
        width: 200.0,
        height: 200.0,
        decoration: new BoxDecoration(
          color: widget.active ? Colors.lightGreen[700] : Colors.grey[600],
          border: _highlight
              ? new Border.all(
                  color: Colors.teal[700],
                  width: 10.0,
                )
              : null,
        ),
      ),
    );
  }
}

StatefulWidget的状态管理可由自身、父类或者两者混合管理。

State生命周期

在这里插入图片描述

State类声明周期如上图所示:
**initState:**当Widget第一次插入到Widget树时会被调用,对于每一个State对象,Flutter framework只会调用一次该回调,所以,通常在该回调中做一些一次性的操作,如状态初始化、订阅子树的事件通知等。
didChangeDependencies()_:_当State对象的依赖发生变化时会被调用;例如:在之前build() 中包含了一个InheritedWidget,然后在之后的build() 中InheritedWidget发生了变化,那么此时InheritedWidget的子widget的didChangeDependencies()回调都会被调用。典型的场景是当系统语言Locale或应用主题改变时,Flutter framework会通知widget调用此回调。
**build():**用于构建Widget子树
reassemble():此回调是专门为了开发调试而提供的,在热重载(hot reload)时会被调用。
didUpdateWidget():在widget重新构建时,framework会调用Widget.canUpdate来检测Widget树中同一位置的新旧节点,然后决定是否需要更新,如果Widget.canUpdate返回true则会调用此回调。canUpdate中实际对比key和runtimeType
_deactivate():_当State对象从树中被移除时,会调用此回调。在一些场景下,framework会将State对象重新插到树中,如包含此State对象的子树在树的一个位置移动到另一个位置时(可以通过GlobalKey来实现)。如果移除后没有重新插入到树中则紧接着会调用dispose()方法。
_dispose():_当State对象从树中被永久移除时调用;通常在此回调中释放资源。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值