Flutter
是Google开源的移动应用框架,一套代码能完成跨平台(Android
和IOS
)移动应用的开发,对于Flutter
而言,其有以下特点:
- 现代响应式框架
- 高速的2D渲染引擎
- 方便快捷的开发工具
- 各种组件库
下面我们将针对Flutter
中的特性做简单介绍。
Widget简介
在Flutter
中,一个页面是由许多个Widget
构建而成的树形结构,Widget
是Flutter
应用的基础组件,相当于Android
原生中的View
组件,一个Widget
使用Dart
语言编写,用于描述一部分可参与用户交互的界面,在Flutter
中,几乎都是用Dart
编写的Widget
组件。
在Android Studio
中新建一个Flutter
项目并运行,运行完成后我们会发现在Android Studio
右侧工具栏出现了Flutter Inspector
选项,在该选项卡内,我们可以更深层级的理解上面这段话。
上图为Flutter Inspector
中的Widgets
面板中的内容(左侧为当前页面的截图),在这里我们可以看到页面上的所有元素都是Widget
。当启动Widget Mode
时,我们可以选中某一个Widget
,同时应用对应区域上也会选中并提示Widget
类型(此模式在真机和虚拟机上均适用,类似于Android
原生的显示布局边界的功能,只不过这里显示的是单个Widget
的边界),同时也会在面板上显示当前Widget
的属性信息,这里就印证了我们前面说的在Flutter
中,几乎都是用Dart
编写的Widget
组件,在界面发生变化时,我们可以通过图中的刷新按钮,来同步Widgets
树到面板中。
随后我们切换到Widgets
左侧的Render Tree
面板:
从图中就可以看出我们的基础页面渲染组成仍然是类似于原生的树形结构。
在Flutter
中,所有元素都是Widget
,并且Widget
之间可以发生嵌套,并不像我们的Android
原生独立出了ViewGroup
,在Flutter
中,Widget
既可以是View
也可以当做ViewGroup
来用,下图中罗列的所有元素都是Widget
,当然还有很多没有列举出来。
在Flutter
中,Widget
分两类,一类具备State状态(StatefulWidget
),一类不具备(StatelessWidget
)即构建后静态不可变,UI界面刷新依赖于状态切换,这样节省了开发的状态管理,使得UI状态管理更加轻松,下图为StatefulWidget
的生命周期:
Flutter框架简介
在Flutter
中,上层Dart
语言编写的App
在编译时被转化为对应的平台语言,执行效率更高。在界面渲染上Flutter
采用Skia
作为底层的图像引擎,渲染速度更快。整体的Flutter Framework
如下图:
Flutter
选用Dart
作为其开发语言,除了其语法开源等方面的因素外,主要还关乎Dart语言的编译方式,Dart
语言有两种编译时:
- Just in time(JIT)
- Ahead of time(AOT)
JIT
编译时支撑了Flutter
的Hot reload
开发模式(即代码热更新,修改后ctrl+s
实时运行到真机或者模拟器上),使得整个开发过程更流畅,对界面的修改实时可见(当然这里的实时是相对Android
原生的UI修改到验证速度而言的,这里重点为了说明其Hot reload
模式的便捷性)。
AOT
编译时支撑了Flutter
的跨平台特性,在运行前编译时会把我们的Dart
代码编译成对应的Arm
代码。
Flutter应用目录结构
我们在Android studio
或者cmd
( 通过flutter create
方式)创建的Flutter
应用一般会生成四个目录
- android
Android
平台的原生代码目录,有一些额外的原生逻辑可在该目录下处理 - ios
IOS
平台的原生代码目录,有一些额外的原生逻辑可在该目录下处理 - lib
跨平台的功能代码目录,该目录下的文件均使用Dart
语言编写,在运行前编译时会将其编译成对应的ARM
代码,一般情况下,开发过程中我们只需要关注该目录就可以,在新建项目的项目中,该目录一般会自动生成main.dart
文件,该文件为整个Dart
部分代码的入口文件,其内部代码如下:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(title: new Text(title),),
body: Container(),
);
}
}
其中main
函数为整个Flutter
部分的入口函数,相当于C
语言的main
函数,整个Flutter
部分的代码调起均在该函数内(这也就意味着我们原来在Application
中进行的数据初始化,全局变量初始化之类的操作,需要在该函数中完成,如果有需要的话)。
runApp
函数指定Flutter
部分的第一个Widget
页面,随后运行就可以看到页面效果了 (这里描述为Flutter
部分的主要原因是有可能存在Flutter
混合原生开发的情况,不过一般存在混合的话会有FlutterActivity
类的子类存在。)
- tests
该目录下主要是Dart
相关的一些测试代码目录