1.概述
- 简介
- Flutter是谷歌开发的一款开源、免费的,基于Dart语言的UI框架,可以快速在IOS和Android上构建高质量的原生应用,它最大的特点就是跨平台和高性能
- Dart是由谷歌在2011年开发的计算编程语言,它可以被用于web、服务器、移动应用和物联网多个领域。号称要取代JavaScript.
跨平台(适用于多个终端)
- 移动端
- Andriod
- IOS
- Web端(各种浏览器)
- 桌面(Windows、Mac)
- 嵌入式平台(Linux、Fuchsia)
跨平台的直接好处是减少开发成本 Flutter的野望,是一统天下
- 移动端
高性能
- Flutter应用的性能,接近原生App.
- Flutter采用GPU(图像显示)渲染技术。
- Flutter应用刷新频率可达120fps(120帧每秒)
- 可以用Flutter来开发游戏
- ReactNative应用的刷新频率只能达到60fps(60帧每秒)
- 刷新频率
- 1950-24fps
- 1956-30fps
- 1992-48fps
- 2011-60fps
- now-120fps
- 发展历程
- 2015,Flutter(当时叫Sky)在Dart开发者峰会上亮相
- 2018-06,Flutter发布了首个预览版本
- 2018-12,Flutter1.0发布
- 2019-9,Flutter1.9发布,添加Web端支持
- 2020-9,Flutter1.22发布,带来了对IOS14和Andriod11的支持
- 当前版本:Flutter1.22.5
跨平台框架的比较 | 框架 | React Native | Week | Flutter | | —- | —- | —- | —- | | 所属公司 | Facebook | Alibaba | Google | | 编程语言 | JavaScript(React) | JavaScript(Vue) | Dart | | 引擎 | JSCore | v8 | Flutter engine | | 支持系统 | Andriod、IOS | Andriod、IOS、Web | Andriod、IOS、Fuchsia | | 性能 | 一般 | 较快 | 较快 | | 适用场景 | 整体App | 单页面 | 整体App | | 学习成本 | 难 | 易 | 一般 |
移动App的开发模式 | 开发模式 | 原生开发 | 混合开发 | Web开发 | | —- | —- | —- | —- | | 运行环境 | Andriod、IOS | Andriod、IOS | 浏览器、WebView | | 编程语言 | Java、Objective-C | JavaScript、Dart | HTML、CSS、JavaScript | | 可移植性 | 差 | 一般 | 好 | | 开发速度 | 慢 | 一般 | 快 | | 性能 | 快 | 较慢 | 慢 | | 学习成本 | 高 | 一般 | 低 |
资源网站
- 官网
- Github
- 中文网
- https://flutterchina.club/
- https://flutter.cn/
2. 环境搭建
基础环境
操作系统
- windows下只能搭建Andriod开发环境
- Mac下既能搭建Andriod开发环境,也能搭建IOS开发环境
- 硬盘空间
- Windows(400M+)
- Mac(700M+)
- Git
- Flutter开发需要Git支持
- 下载
- 安装
- 双击下一步
- 验证
- git —version
- VS Code
- 安装VS Code
- 在VS Code中安装Flutter插件
- 搭建Flutter网络环境
- 翻墙
搭建Windows下的安卓环境
- JDK
- Andriod Studio
- 安装Andriod Studio
- 安装Andriod SDK
- 安装Andriod模拟器
- Flutter SDK
- 直接下载
- Git下载
配置资源镜像
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
找到我的电脑-》右键点击属性-》点击高级系统设置-》参考下面
JDK简介
- JDK是Java开发套件的简称。既然要做原生应用,而且是基于Andriod的,所以,需要安装JDK。
- 下载
- https://www.oracle.com/java/technologies/downloads/#java8
- 下载时,提示需要登陆,我们可以先注册一个Oracle账户,登录后直接下载
- 安装好后配置环境变量,打开命令行java —version验证
- 验证
- 安装完成后,重新打开命令行(win+r 然后输入 cmd 回车),输入 java -version,然后回车,验证安装是否成功(看到版本号,说明 JDK 安装成功)。
- 如果看不到效果。需要将 JDK 的安装路径,绑定的环境变量中。然后,重新打开命令行验证。
找到 我的电脑 => 右键 点击 属性 => 点击 高级系统设置 => 参考下图
- 然后将安装的 Java 路径,声明为 JAVA_HOME配置完成后,再次执行上述 验证,确保 Java 命令可以运行
- 如果还无效,最终的解决办法是:cmd中输入:set path=”%JAVA_HOME%\bin”
- 成功如图:
Andriod Studio
- 下载
- 点击下一步只至完成(必须翻墙)
- 安装插件
- File -> Setting -> Plugin -> 搜索flutter -> install
- 安装SDK
- 正常来说可以忽略这一步,因为Andriod Studio默认会安装最新版本的Andriod SDK,如果最新的SDK存在兼容性问题,这里你可以单独安装指定版本的Andriod SDK。
- 打开Andriod Studio,在菜单Tools下找到SDK Manager
- 安装模拟器tools -> AVD Manager
- 安装Flutter插件
- https://docs.flutter.dev/development/tools/sdk/releases
- 下载好后解压到D盘,配置环境变量,全局注册flutter指令
- 命令行运行flutter doctor,可以检测flutter环境条件是否满足。一般来说会有一些问题。(没问题的是绿色箭头,有问题的是叹号或×号)
- flutter doctor —android-licenses,安装证书,一路输y即可
- 安装成功,环境搭建完毕
3.项目初体验
- 初始化flutter项目
- 通过命令行 ```bash flutter create myproject cd myproject flutter run
列出手机列表
flutter emulators
启动手机 flutter emulators —launch Pixel_3a_API_30
flutter emulators —launch
- 通过Andriod Studio
- 必须安装flutter插件
- 通过VS Code(推荐)
- 必须安装flutter插件
- 修改gradle文件镜像地址为国内地址
- flutter中修改下面文件 flutter/packages/flutter_tools/gradle/flutter.gradle
```java
buildscript {
repositories {
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/jcenter' }
maven { url 'https://maven.aliyun.com/nexuscontent/groups/public' }
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.0'
}
}
- 项目中配置gradle仓库 ```java buildscript { repositories { maven { url ‘https://maven.aliyun.com/repository/google‘ } maven { url ‘https://maven.aliyun.com/repository/jcenter‘ } maven { url ‘https://maven.aliyun.com/nexuscontent/groups/public‘ } google() jcenter() } }
allprojects { repositories { maven { url ‘https://maven.aliyun.com/repository/google‘ } maven { url ‘https://maven.aliyun.com/repository/jcenter‘ } maven { url ‘https://maven.aliyun.com/nexuscontent/groups/public‘ } google() jcenter() } }
<a name="CzNd0"></a>
### 4.Dart概述
**Dart简介**
- Dart是谷歌开发的,类型安全的,面向对象的编程语言,被应用于Web、服务器、移动应用和物联网等领域。
- Dart诞生于2011年10月10日
- Dart简单易学(类似TypeScript,是强类型语言)
- 运行方式
- 原生虚拟机(Dart代码可以运行在windows,Mac,Linux上)
- JavaScript引擎(Dart代码可以转成JS代码,然后运行在浏览器上)
| Dart | JavaScript |
| --- | --- |
| Flutter | React |
| https://pub.dev | https://npmjs.com |
| pub | npm |
**Dart环境搭建**
- 从Flutter1.21版本开始,Flutter SDK会同时包含完整的Dart SDK。
- 如果你已经安装了Flutter,就无需下载Dart SDK了
- 官网介绍:https://dart.cn/get-dart
**Dart环境搭建-绑定环境变量**
- 先确定Flutter SDK的安装路径
- 我的是D:\flutter
- D:\flutter\bin
- Flutter和Dart的相关执行命令
- D:\flutter\bin\cache\dart-sdk\bin
- Dart SDK的相关命令的执行路径
- D:\flutter\.pub-cache\bin
- Pub下载的公共模块的执行路径
**Dart资源网站**
- 官网
- 英文 https://dart.dev
- 中文 https://dart.cn
- 在线运行代码
- https://dartpad.dartlang.org
- https://dartpad.cn
- 生态
- https://pub.dev
<a name="Hr9io"></a>
### 5.Dart基础
```dart
// 声明变量
void printInterger(int aNumber) {
print('The number is $aNumber')
}
// 入口文件-应用从这里开始执行
void main() {
var number = 42; // 声明一个变量
printInteger(number); // 调用函数
}
语法基础
- 注释语法和JS一致
- 声明函数不需要关键字(JS通过function关键字来声明函数)
- 函数与参数前面都有类型声明,void表示没有返回值,int是整型数字
- 打印使用print(JS使用console.log)
- 每行代码结束时,必须写分号
- 字符串通过引号包起来,支持模板字符串
- main是入口函数,Dart应用程序总是从main函数开始执行
- 用var声明的变量,其数据类型是动态的
语法基础-运行
在命令行中运行
- dart hello.dart
Dart 执行文件中的main函数
void main() {
print('hello world')
}
输出hello world
语法基础-注释
- 单行注释
- // 我是单行注释
- 多行注释
- / 我是多行注释 /
- 文档注释
- /// 我是文档注释
- 可以通过dartdoc将注释转为文档(文档注释支持markdown语法)
语法基础-变量
- 变量是一个引用,Dart万物皆对象,变量存储的是对象的引用
- 声明变量
- 明确指定类型:int age = 18;
- 不明确类型:var age = 18;或dynamic age = 18;
- 变量名大小写敏感(age和Age是两个不同的变量)
- 变量的默认值是null(JS中是undefined)
- Dart变量的值不会进行隐式转换(null不会自动转成false)
语法基础-常量
- 常量就是不可变的变量(一旦声明,其值不能更改)
- 声明常量
- const age = 18;
- final age = 18;
const和final的区别
Dart中的数字由三个关键字描述
- num数字类型(即可以是整数,也可以是小数)
- int表示整数(必须是整数)
- double表示浮点数(可以是整数也可以是浮点数)
- 常用API
String
- 声明字符串(String)
- 单引号、双引号都可以
- 三个引号可以声明包含换行符的字符串
- 常见API
- 正则表达式
- RegExp(r’正则表达式’)
- RegExp(r’\d+’)
Boolean
- Dart通过bool关键字来表示布尔类型
- 布尔类型只有两个值:true和false
- 对变量进行判断时,要显示地检查布尔值
List
- Dart中的数组,由List对象表示,List有两种声明方式
- 字面量方式
- List list = []; // 不限定原素的数据类型
- List list =
[]; // 限定元素的数据类型为int
- 构造函数方式
- List list = new List.empty(growable: true); // 不限制长度的空列表
- List list = new List.filled(3, 0); // 声明指定长度的填充列表
- 字面量方式
- 扩展操作符(…)
- var list = [1, 2, 3];
- var list2 = [0, …list]; // [0, 1, 2, 3]
- 常用API
遍历List
- forEach()
- 遍历列表
- map()
- 遍历并处理元素,然后生成新的列表
- where()
- 返回满足条件的数据
- any()
- 只要有一项满足条件,即返回true
- every()
- 判断是否每一项都满足条件,满足条件才返回true
Set
- Set是一个无序的,元素唯一的集合
- Set有字面量和构造函数两种声明方式(字面量中用大括号)
- 无法通过下标取值
- 具有集合特有的操作
- 例如:求交集、并集、差集等
- 常用API
Map
- Map是一个无序的键值对(key-value)映射。通常被称为哈希或字典
- 声明方式
- var map = {key1: value1, key2: value2}
- var map = new Map();
- map[‘key’] = value
- 常用API
其它
- Runes(符文)
- Runes对象是一个32位字符对象,它可以把文字转换成符号表情或特定的文字
- print(‘\u{1f44d}’)
- https://copychar.cc/
- Symbol
- 在Dart中符号用#开头来表示的标识符
dynamic
地板除(~/)向下取整
- 类型判断运算符(is | is!)
- 避空运算符(?? | ??=)
- 条件属性(?.)
级联运算符(..)
直接声明
- Dart中声明函数不需要function关键字
- 箭头函数
- Dart中的箭头函数中,函数体只能写一行且不能带有结束的分号
- Dart中的箭头函数,只是函数的一种简写形式
- 匿名函数
- 立即执行函数
函数参数
- 必填参数
- 参数类型 参数名称
- 可选参数
- 放在必填参数后面
- 通过中括号包裹起来
- 带默认值的可选参数
- 命名参数
- 用大括号包裹起来
- 调用函数时,命名参数的名称与声明函数中的名称保持一致
- 函数参数
作用域和闭包
- 作用域:就是变量的作用范围。内层作用域可以访问外层作用域的变量,反之不行
- 闭包
- Dart中闭包的实现方式与JavaScript中完全一致
- 使用时机:即能重用变量,又保护变量不被污染
- 实现原理:外层函数被调用后,外层函数的作用域对象(AO)被内层函数引用着,导致外层函数的作用域对象无法释放,从而形成闭包
异步函数
- JavaScript中,异步调用通过Promise来实现
- async函数返回一个Promise,await用于等待Promise
- Dart中,异步调用通过Future来实现
- async函数返回一个Future,await用于等待Future
Future详情
类是通过class声明的代码段,包含属性和方法。
- 属性:用来描述类的变量
- 方法:类中的函数称为类的方法
- 类是对具体事物的抽象,对象是类的实例化的结果(var obj = new MyClass())
- 面向对象编程(OOP)
- 面向过程编程(POP)
构造器(构造函数)
- 默认构造函数
- 与类同名的函数,在实例化时,自动被调用
- 命名构造函数
- 在类中使用命名构造器(类名.函数名)实现多个构造器,可以提供额外的清晰度
- 常量构造函数
- 如果类生成的对象不会改变,就可以通过常量构造函数时这些对象称为编译时的常量
- 工厂构造函数
- 通过factory声明,工厂函数不会自动生成实例而是通过代码来决定返回的实例
访问修饰符
- Dart与TypeScript不同,没有访问修饰符(public、protected、private)
- Dart类中,默认的访问修饰符是公开的(即public)
- 如果属性或方法以_(下划线)开头,则表示私有(即private)
- 只有把类单独抽离出去,私有属性和方法才会起作用
- lib/Person.dart
- import ‘lib/Person.dart’
Getter与Setter
- Getter(获取器)是通过get关键字修饰的方法
- 函数没有小括号,访问时也没有小括号(象访问属性一样访问方法)
- Setter(修改器)是通过set关键字修饰的方法
- 访问时,象设置属性一样给函数传参
初始化列表
- 作用:在构造函数中设置属性的默认值
- 时机:在构造函数体执行之前执行
- 语法:使用逗号分隔初始化表达式
场景:常用于设置final常量的值
class Rect {
int height;
int width;
// 必填参数
// Rect(this.height, this.width);
// 可选参数
// Rect([int height = 2, int width = 10]) {
// this.height = height;
// this.width = width;
// // 访问对象的属性需要{}
// print('${this.height}---${this.width}');
// }
// 命名参数
// Rect({int height = 2, int width = 10}) {
// this.height = height;
// this.width = width;
// // 访问对象的属性需要{}
// print('${this.height}---${this.width}');
// }
// 初始化列表
Rect()
: height = 2,
width = 2 {
print("${this.height}---${this.width}");
}
getArea() {
return this.height * this.width;
}
}
static
static关键字用来指定静态成员
- 通过static修饰的属性是静态属性
- 通过static修饰的方法是静态方法
- 静态成员可以通过类名称直接访问(不需要实例化)
- 实例化时比较消耗资源的,声明静态成员,可以提高程序性能
- 静态方法不能访问非静态成员,非静态方法可以访问静态成员
- 静态方法中不能使用this关键字
- 不能使用this关键字,访问静态属性
元数据
- 元数据以@开头,可以给代码标记一些额外的信息
- 元数据可以用来库,类,构造器,函数,字段,参数或变量声明的前面
- @override(重写)
- 某方法添加该注解后,表示重写了父类中的同名方法
- @required(必填)
- 可以通过@required来注解Dart中的命名参数,用来指示它是必填参数
- @deprecated(弃用)
- 若某类或某方法加上该注解之后,表示此方法或类不再建议使用
继承
- 根据类的先后顺序,可以将类分为父类和子类
- 字类通过extends关键字继承父类
- 继承后,子类可以使用父类中,可见的内容(属性或方法)
- 子类中,可以通过@override元数据来标记复写的方法
- 复写方法:子类中与父类中同名的方法
- 子类中,可以通过super关键字来引用父类中可见的内容
- 属性
- 方法(普通构造函数,命名构造函数)
抽象类
- 抽象类是用abstract关键字修饰的类
- 抽象类的作用是充当普通类的模板,约定一些必要的属性和方法
- 抽象方法是指没有方法体的方法
- 抽象类一般都有抽象方法,也可以没有抽象方法
- 普通类中,不能有抽象方法
- 抽象类是不能被实例化(不能被new)
- 抽象类可以被普通类继承(extends)
- 如果普通类继承抽象类,必须实现抽象类中所有的抽象方法
抽象类还可以充当接口被实现
接口在Dart中就是一个类(只是用法不同)
- 与Java不同,Java中接口需要用interface关键字声明;Dart中不需要
- 接口可以是任意类,但一般使用抽象类做接口
- 一个类可以实现(implements)多个接口,多个接口用逗号分隔
- class MyClass implements interface1, interface2 {}
- 接口可以看成一个个小零件。类实现接口就相当于组装零件
-
11.混入(Mixin)
混入是一段公共代码。混入有两种声明方式
- 将类当作混入 class MixinA {}
- 作为Mixin的类只能继承自Object,不能继承自其它类
- 作为Mixin的类不能有构造函数
- 使用mixin关键字声明mixin MixinB{}
- 将类当作混入 class MixinA {}
- 混入可以提高代码复用的效率,普通类可以通过with来使用混入
- class MyClass with MixinA, MixinB{}
使用多个混入时,后引入的混入会覆盖之前混入的重复的内容
泛型是在函数、类、接口中指定宽泛的数据类型的语法
- 泛型函数
- 泛型类
- 泛型接口
- 通常,在尖括号中,使用一个字母来代表类型,列如E,T,S,K和V等。
- 返回类型 函数名<输入类型> (参数类型 参数) { 函数体 }
- T getData
(T value) { return value; }
-
13.枚举
枚举是数量固定的常量值,通过enum关键字声明
- enum Color { red, green, blue }
- 枚举的values常量可以获取所有枚举值列表
- List
colors = Color.values;
- List
可以通过index获取值的索引
Dart中的库就是具有特定功能的模块
- 可能包含单个文件,也可能包含多个文件
- 按照库的作者进行划分,库可以分为三类
- 自定义库(工程师自己写的)
- 系统库(Dart中自带的)
- 第三方库(Dart生态中的)
- Dart生态
- https://pub.dev/
- pub命令(D:\flutter\bin\cache\dart-sdk\bin)
自定义库-通过library来声明库
- 每个Dart文件默认都是一个库,只是没有使用library来显示声明 ```dart // main.dart void main() { print(‘Hello world’); }
// main.dart library main; // 默认隐藏了一个main的library的声明 main() { print(‘Hello world’); }
- Dart使用_(下划线)开头的标识符,表示库内访问可见(私有)
- library关键字声明的库名称建议使用:小写字母+下划线
**自定义库-通过import来引入库**
- 不同类型的库,引入方式不同
- 自定义库(import '库的位置/库名称.dart')
- 系统库 (import 'dart:库名称')
- 第三方库
- 引入部分库(仅引入需要的内容)
- 包含引入(show)
- 排除引入(hide)
- 指定库的前缀
- 当库名冲突时,可以通过as关键字,给库声明一个前缀
- 延迟引入(懒加载)
- 使用deferred as关键字来标识需要延时加载的库
- part与part of
```dart
// 分库
// sub1.dart
part of utill; // 和主库建立联系
int foo() {}
// sub2.dart
part of util;
int bar() {}
// 主库
library util;
// 和子库建立联系
part 'sub1.dart';
part 'sub2.dart';
String hello() {}
// 使用
import 'util.dart';
void main() {
foo();
bar();
hello();
}
系统库
- 系统库(也叫核心库)是Dart提供的常用内置库
- 不需要单独下载,就可以使用
- 引入
- import ‘dart:库名’;
- import ‘dart:core’; // 会自动引入
- 系统库 列表
第三方库
- 来源
- 使用
- 在项目目录下创建pubspec.yaml
- 在pubspec.yaml中声明第三方库(依赖)
- 命令行中进入pubspec.yaml所在目录,执行pub get进行安装
- 项目中引入已安装的第三方库(import ‘package:xxxx/xxxx.dart’;);
- 结构
- 一个第三方库,必须包含一个pubspec.yaml
- pubspec.yaml