-
工具:要让 Flutter 在你的开发环境中正常使用,依赖于以下的工具:
-
Windows PowerShell 5.0 或者更高的版本(Windows 10 中已预装)
-
Git for Windows 2.x,并且勾选从 Windows 命令提示符使用 Git 选项。
如果 Windows 版的 Git 已经安装过了,那么请确保能从命令提示符或者 PowerShell 中直接执行 git 命令。D:\Program Files\flutter\bin
-
一、入门
1.配置
1)Flutter SDK
-
点击下方的安装包,获取 stable 发行通道的 Flutter SDK 最新版本:
https://flutter.cn/docs/get-started/install/windows#
要查看其他发行通道和以往的版本,请参阅 SDK 版本列表 页面。
-
将压缩包解压,然后把其中的
flutter
目录整个放在你想放置 Flutter SDK 的路径中(例如C:\src\flutter
)。
请注意
请勿将 Flutter 有特殊字符或空格的路径下。
请注意
请勿将 Flutter 安装在需要高权限的文件夹内,例如 C:\Program Files\
。
现在你可以在控制台当中使用 Flutter 的命令了。
2)更新 path
如果你想在 Windows 控制台中运行 Flutter 命令,需要按照下面的步骤来将 Flutter 的运行文件路径加入到 PATH
环境变量。
- 在开始菜单的搜索功能键入「env」,然后选择 编辑系统环境变量。
- 在 用户变量 一栏中,检查是否有 Path 这个条目:
- 如果存在这个条目,以
;
分隔已有的内容,加入flutter\bin
目录的完整路径。 - 如果不存在的话,在用户环境变量中创建一个新的
Path
变量,然后将flutter\bin
所在的完整路径作为新变量的值。
- 如果存在这个条目,以
你需要重新打开已经打开的命令行提示符窗口,这样下次启动命令提示符时,才能访问到刚才修改的变量。
提示
自 Flutter 1.19.0 dev 版本开始,Flutter SDK 在 flutter
命令脚本的同级目录下增加了 dart
命令,你可以更方便地运行 Dart 命令行程序。下载 Flutter SDK 时也会下载对应版本的 Dart SDK,但如果你单独下载了 Dart SDK,请确保 Flutter SDK 内的 dart
在你的环境变量中排在首位,因为单独的 SDK 可能并不兼容 Flutter SDK。下面的命令展示了 flutter
和 dart
是否来自相同的 bin
目录,并且是否可以兼容使用。
C:\>where flutter dart
C:\path-to-flutter-sdk\bin\flutter
C:\path-to-flutter-sdk\bin\flutter.bat
C:\path-to-dart-sdk\bin\dart.exe :: this should go after `C:\path-to-flutter-sdk\bin\` commands
C:\path-to-flutter-sdk\bin\dart
C:\path-to-flutter-sdk\bin\dart.bat
如上所示,Flutter SDK 内的 dart
命令不在首位。你需要更新 PATH,将 C:\path-to-flutter-sdk\bin\
放在 C:\path-to-dart-sdk\bin\
前面(当前场景)。接着重启命令行使修改生效,再次运行 where
,此时来自相同目录的 flutter
和 dart
已经排在前面。
C:\>where flutter dart
C:\dev\src\flutter\bin\flutter
C:\dev\src\flutter\bin\flutter.bat
C:\dev\src\flutter\bin\dart
C:\dev\src\flutter\bin\dart.bat
C:\dev\src\dart-sdk\bin\dart.exe
然而,如果你在使用 PowerShell
,where
其实是 Where-Object
命令的别名,所以实际上你需要运行 where.exe
。
PS C:\> where.exe flutter dart
了解更多 dart
命令的用法,可以在命令行中运行 dart -h
查看,也可以访问 DartVM 运行环境。
Android Studio 的 Flutter 或者 Dart 插件安装
2.基础语法
1)入口方法
main(){
print('hello dart');
}
// void代表没有返回值
void main(){
print('hello dart');
}
2)注释
// 单行注释
/*
多行注释
*/
/**
文档注释
*/
/// 使用三个斜杠开头
///这是Dart特有的文档注释
3.Dart命名规则
1)变量名称必须有数字,字母,下划线,和美元符号($)组成
2)标识符的开头不能是数字开头
3)标识符不能使用关键字和保留字
4)变量的名称是会区分大小写的
5)定义标识符的时候意思要尽量明朗,通常变量的名称使用名词,方法的名称使用动词
4.Dart变量
Dart中定义变量有两种方式,一种是静态类型语言常用的方式,显式指定变量类型,另一种则是动态语言的常用方式,不指定类型,由vm自动推断。可通过var关键字声明变量,也可通过显式类型声明
// 1.通过显式指定类型来定义变量
String name ="张三";
num age = 18;
// 2.使用关键字var,不指定类型
var address ="深南大道";
var id = 100;
/*
使用var定义变量,即使未显式指定类型,一旦赋值后类型就被固定因此使用var定义的变量不能改变数据类型
*/
var number = 19;
// 以下代码错误,无法运行,number变量已确定为int类型
number = "2019"
注意: var关键字和具体类型不要同时写,如:var int str =123; 报错
如想动态改变变量的数据类型,应当使用dynamic
或Object
来定义变量。
// dynamic声明变量
dynamic varl = "hello";
var1 = 19;
print(var1);
// 19
// object声明变量
Object var2 = 20;
var2 ="Alice";
print(var2);
// Alice
5.Dart常量
Dart的常量使用final和const修饰
- const修饰的常量在一开始的时候就需要赋值(编译的时候就已经赋好值了)
- final修饰的常量可以在一开始的时候不赋值,但同样只能赋值一次(惰性赋值,运行时第一次使用时赋值)
// const常量
const PI = 3.14159;
PI = 3; //错误,常量的值不能修改
// final常量
final a = new DateTime.now(); //给a运行时赋值
需要注意,final
定义的常量是运行时常量,而const
常量则是编译时常量,也就是说final
定义常量时,其值可以是一个变量,而const
定义的常量,其值必须是一个字面常量值。
final time = new DateTime.now(); // 正确
const time = new DateTime.now(); // 错误
const list = const[1,2,3]; // 正确
const list = [1,2,3]; // 错误
二、数据类型
1.基本类型
常用的数据类型:
- Numbers(数值):int,double
- Strings(字符串) : String
- Booleans(布尔) : bool
- List(数组) : 在Dart中数组是列表对象
- Maps(字典) : Map为键值对相关对象
在Dart中,所有能够使用变量引用的都是对象,每个对象都是一个类的实例。数字、函数和 null 也都是对象。所有的对象都继承于Object类。要注意,没有初始化的变量默认值为 null。数值类型变量的默认值也是 null。
1)数值类型
数值类型num有两个具体子类,分别为int和double,其中int为整数值,范围是-253至253之间;double则是64位的双精度浮点数。
int 整型
int a = 1;
var a = 1;
int a = 1.4; // 报错
指明数据类型则变量不为空
int a=123; //非空的int类型
a=null; //A value of type 'Null' can't be assigned to a variable of type 'int'
double 浮点型
double b = 2.5;
double b = 2 ; // 给浮点型变量赋值整型不会报错,但输出的结果会自动补小数点后的0
2)字符串类型
可以用单引号,也可以用双引号
var str1 = ' i am str1';
或
String str1 = ' i am str1';
var str2 = "i am str2";
或
String str2 = "i am str2";
使用三引号定义字符串可以换行
String str3='''
i am str1
i am str2
i am str3''';
或:
String str3="""
i am str1
i am str2
i am str3""";
字符串拼接
// 方式一
print("$str1 $str2");
// 方式二
print(str1 + " " + str2);
指明数据类型则变量不为空
String username="张三"; //非空的String类型
username=null; //A value of type 'Null' can't be assigned to a variable of type 'String'.
Dart中提供的字符串插值表达式
使字符串格式化方便
// 1.Dart可以使用单引号或双引号来创建字符串
var sl = "hello";
var s2 = 'world' :
// 2.类似Python,Dart可以使用三引号来创建包含多行的字符串
var multiLinel ="""你可以像这样,创建
一个包含了多行的字符串内容"""
var multiLine2 = '''你也可以使用三个单引号,创建一个
包含了多行的字符串内容'''
//3.类似Python,还可以在字符串字面值的前面加上广来创建原始字符串,则该字符串中特殊字符可以不用转义
var path = r'D: wo rkspace code';
// 4.Dart支持使用"+”操作符拼接字符串
var greet = "hello" +" world":
// 5.Dart提供了插值表达式"$tJ",也可以用于拼接字符串
var name ="王五";
var astr = "hello, ${name}";
print(aStr);
// hello,王五
//当仅取变量值时,可以省略花括号
var astr2 = "hello,$name";
// hello,王五
//当拼接的是一个表达式时,则不能省略花括号
var strl ="ink":
var str2 = "click fstrl.toUpperCase()}";
print(str2);
// click LINK
// 6.与Java不同,Dart使用"=="来比较字符串的内容
print("hello" == "world"):
3)布尔类型
Dart中的布尔类型用法同Java,仅有false
、true
两个值,不能使用 0、非 0 或者null
、非null
来表达false
和true
。与Java不同的是,布尔类型的默认值为null
bool b1 = true;
bool b2 = false;
bool flags;
print(flags); // n
ull
2.List类型
1)定义
Dart数据类型: List(数组/集合)
1、第一种定义List的方式
var l1 = ["张三", 20, true];
print(l1); //[张三, 20, true]
print(l1.length); //3
print(l1[0]); //张三
print(l1[1]); //20
var list = [1,2,3];
// 下标从0开始。使用length可以访问list的长度
print(list[0]);
// 可在List字面量前添加const关键字,定义一个不可改变的 列表(编译时常量)
var constantList = const [1, 23];
constantList[1] = 1; // 报错
2、第二种定义List的方式 指定类型
var l2 = <String>["张三", "李四"];
print(l2);
var l3 = <int>[12, 30];
print(l3);
3、第三种定义List的方式 增加数据 ,通过[]创建的集合它的容量可以变化
var l4 = [];
print(l4);
print(l4.length);
l4.add("张三");
l4.add("李四");
l4.add(20);
print(l4);
print(l4.length);
var l5 = ["张三", 20, true];
l5.add("李四");
l5.add("zhaosi");
print(l5);
4、第四种定义List的方式
// var l6 = new List(); //在新版本的dart里面没法使用这个方法
var l6 = List.filled(2, ""); //创建一个固定长度的集合
print(l6);
print(l6[0]);
l6[0] = "张三"; //修改集合的内容
l6[1] = "李四";
print(l6); //[张三, 李四]
l6.add("王五"); //错误写法 通过List.filled创建的集合长度是固定 没法增加数据
//通过List.filled创建的集合长度是固定,可指定传入类型
var l6 = List.<String>filled(2, "");
print(l6.length);
l6.length = 0; //修改集合的长度 报错
指明数据类型则变量不为空
List<String> l1 = ["张三", "李四", "王五"];
l1 =
null; //A value of type 'Null' can't be assigned to a variable of type 'List<String>'.
2)属性
常用属性:
length 长度
reversed 翻转
isEmpty 是否为空
isNotEmpty 是否不为空
List myList=['香蕉','苹果','西瓜'];
// List myList=['香蕉','苹果','西瓜']; 不可重新赋值
// List里面的属性:
print(myList.length);
// 3
print(myList.isEmpty);
// false
print(myList.isNotEmpty);
// true
print(myList.reversed); //对列表倒序排序
// (西瓜, 苹果, 香蕉)
var newMyList=myList.reversed.toList();
print(newMyList);
// [西瓜, 苹果, 香蕉]
3)方法
方法名 | 作用 |
---|---|
cast | 将一个数组的类型传递给未指定数据类型的数组 |
List.generate | 快速生产 Flutter 中的 Widget |
reduce | 用指定的函数方式对数组中的所有元素做连续操作,并将结果返回 |
fold | 根据一个现有数组和一个初始参数值 initValue,指定参数条件操作现有数组的所有元素,并返回处理的结果 |
expand | 根据现有数组,指定一个处理方式,返回一个 Iterable |
// cast 将一个数组的类型传递给未指定数据类型的数组
List<int> l1 = [8, 12, 8];
var l2 = l1.cast(); // 指定 l2 的数据类型和 l1 的一样,都是 int 类型
l2.add(6);
print(l1); // [8, 12, 8, 6]
l2.add("ddd");
print(l1); // 报错,提示无法将 String 类型的数添加到 int 类型的数组中
// List.generate 快速生产 Flutter 中的 Widget
List<int> l1 = [8, 12, 8, 6, 22, 12, 10];
...
children: List.generate(l1.length, (index){
return Text("$index");
})
// reduce 用指定的函数方式对数组中的所有元素做连续操作,并将结果返回
List<int> l1 = [1, 2, 3, 4];
int res1 = l1.reduce((a, b) => (a * b)); // 元素依次相乘
int res2 = l1.reduce((a, b) => (a + b)); // 元素依次相加
print(res1); // 1*2*3*4 = 24
print(res2); // 1+2+3+4 = 10
// fold 根据一个现有数组和一个初始参数值 initValue,指定参数条件操作现有数组的所有元素,并返回处理的结果
List<int> l1 = [1, 2, 3, 4];
// 2 为初始参数值,后面定义的方法为该初始值和原数组之间的处理方式
int res1 = l1.fold(2, (a, b) => (a * b)); // 相乘
int res2 = l1.fold(2, (a, b) => (a + b)); // 相加
print(res1); // 2*(1*2*3*4) = 48
print(res2); // 2+(1+2+3+4) = 12
// expand 根据现有数组,指定一个处理方式,返回一个 Iterable
List<int> l1 = [1, 2, 3, 4];
// 将 l1 数组内的每一个元素都和指定的表达式组相操作
Iterable<int> l2 = l1.expand((e) => [e + 1]);
Iterable<int> l3 = l1.expand((e) => [e + 1, e + 2]);
Iterable<int> l4 = l1.expand((e) => [e + 2, e * 2]);
Iterable<num> l5 = l1.expand((e) => [e * 2, e / 2]);
Iterable<int> l6 = l1.expand((e) => [e, e + 1, e + 2]);
print(l2); // (2, 3, 4, 5)
print(l3); // (2, 3, 3, 4, 4, 5, 5, 6)
print(l4); // (3, 2, 4, 4, 5, 6, 6, 8)
print(l5); // (2, 0.5, 4, 1.0, 6, 1.5, 8, 2.0)
print(l6); // (1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 6)
增
"添加"数据的方法
方法名 | 作用 |
---|---|
add | 添加一个元素到数组末尾 |
addAll | 合并两个数组 |
insert | 在指定索引处插入一个值 |
insertAll | 在指定索引处插入一个数组 |
// add 添加一个元素到数组末尾
List<String> l1 = ["周一", "周二", "周三"];
l1.add("周四");
l1.add("周五");
print(l1);
// [周一, 周二, 周三, 周四, 周五]
// 需要注意的是,你不能向一个固定长度的数组用 add() 方法添加元素,否则会抛出异常
List<String> l2 = List(1);
l2.add("Allen Su");
// addAll 合并两个数组
List<String> l1 = ["周一", "周二", "周三"];
List<String> l2 = ["周四", "周五", "周六","周日"];
l1.addAll(l2);
print(l1);
// [周一, 周二, 周三, 周四, 周五, 周六, 周日]
// 因为 List 和 Set 都继承于 Iterable,所以 List 可以直接当 addAll() 方法的参数使用。需要注意的是,你不能向一个固定长度的数组用 addAll() 方法添加元素,否则会抛出异常,如下代码所示
List<String> l4 = List(1);
l4.addAll(["Allen Su"]);
print(l4);
// insert 在指定索引处插入一个值
List<String> l1 = ["周一", "周二", "周三"];
l1.insert(3, "周四");
print(l1);
// [周一, 周二, 周三, 周四]
l1.insert(0, "周日");
print(l1);
// [周日, 周一, 周二, 周三, 周四]
// insertAll 在指定索引处插入一个数组
List<String> l1 = ["周一", "周二", "周三"];
List<String> l2 = ["周四", "周五", "周六", "周日"];
l1.insertAll(0, l2);
print(l1);
// [周四, 周五, 周六, 周日, 周一, 周二, 周三]
删
- 如果数组中有该数据或者满足删除的条件,则删除,原数组发生改动。
- 如果要删除的数据不在数组中,或者删除元素的条件不成立,也不会报错,返回原数组。
方法名 | 作用 |
---|---|
remove | 删除指定元素 |
removeAt | 删除指定索引位置处的元素 |
removeLast | 删除数组的最后一个元素 |
clear | 清空数组 |
removeWhere | 根据指定条件删除元素 |
removeRange | 删除指定索引范围内的元素(含头不含尾) |
// remove 删除指定元素 查看更多
List<String> l1 = ["周一", "周二", "周三","周一"];
l1.remove("周一");
print(l1); // [周二, 周三, 周一]
// removeAt 删除指定索引位置处的元素
List<String> l1 = ["周一", "周二", "周三"];
l1.removeAt(0);
print(l1); // [周二, 周三]
// removeLast 删除数组的最后一个元素
List<String> l1 = ["周一", "周二", "周三"];
l1.removeLast();
print(l1); // [周一, 周二]
// clear 清空数组
List<String> l1 = ["周一", "周二", "周三"];
l1.clear();
print(l1); // []
// removeWhere 根据指定条件删除元素
List<String> l1 = ["周一", "周二", "周三"];
l1.removeWhere((e) => e == "周二");
print(l1); // [周一, 周三]
List<String> l2 = ["周一", "周二", "周三","星期四"];
l2.removeWhere((e) => e.contains("周"));
print(l2); // [星期四]
// removeRange 删除指定索引范围内的元素(含头不含尾)
List<String> l1 = ["周一", "周二", "周三","周四", "周五", "周六", "周日"];
l1.removeRange(2, 5);
print(l1); // [周一, 周二, 周六, 周日]
改
方法名 | 作用 |
---|---|
List [index] | 修改指定索引位置元素的值 |
toSet | 将 List 转换为 Set,得到去重后的元素 |
asMap | 将 List 转换为 Map,key 为原数组的索引,value 为原数组的元素 |
sort | 数组排序(原数组发生改变) |
shuffle | 随机排列指定数组(修改了原数组) |
join | 用指定字符连接数组中每个元素,返回 String |
fillRange | 用相同的值替换指定索引范围内的所有元素(含头不含尾) |
replaceRange | 用某一数组替换指定索引范围内的所有元素(含头不含尾) |
setRange | 范围替换数组中的值(含头不含尾) |
setAll | 从指定索引位置开始,使用第二个数组内的元素依次替换掉第一个数组中的元素 |
// List [index] 修改指定索引位置元素的值
List<String> l1 = ["周一", "周二", "周三", "星期四"];
l1[3] = "周四";
print(l1); // [周一, 周二, 周三, 周四]
// toSet 将 List 转换为 Set,得到去重后的元素
List<int> l1 = [8, 12, 8, 6, 22, 12, 10];
Set<int> l2 = l1.toSet();
print(l2);
// {8, 12, 6, 22, 10}
// asMap 将 List 转换为 Map,key 为原数组的索引,value 为原数组的元素
List<String> l1 = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"];
Map map = l1.asMap();
print(map); // {0: 周一, 1: 周二, 2: 周三, 3: 周四, 4: 周五, 5: 周六, 6: 周日}
// sort 数组排序(原数组发生改变)
List<int> l1 = [8, 12, 8, 6, 22, 12, 10];
l1.sort();
List<String> l2 = ["f", "d", "b", "c", "a", "e"];
l2.sort();
print(l1); // [6, 8, 8, 10, 12, 12, 22]
print(l2); // [a, b, c, d, e, f]
// shuffle 随机排列指定数组(修改了原数组)
List<int> l1 = [1, 2, 3, 4];
l1.shuffle();
print(l1); // [1, 4, 2, 3]
l1.shuffle();
print(l1); // [2, 1, 3, 4]
// join 用指定字符连接数组中每个元素,返回 String
List<int> l1 = [8, 12, 8, 6, 22, 12, 10];
String str1 = l1.join();
String str2 = l1.join("");
String str3 = l1.join(" ");
String str4 = l1.join(",");
String str5 = l1.join("-");
print(str1); // 81286221210
print(str2); // 81286221210
print(str3); // 8 12 8 6 22 12 10
print(str4); // 8,12,8,6,22,12,10
print(str5); // 8-12-8-6-22-12-10
// fillRange 用相同的值替换指定索引范围内的所有元素(含头不含尾)
List<String> l1 = ["周一", "周二", "周三", "周四", "周五"];
l1.fillRange(1, 4, "AllenSu");
print(l1); // [周一, AllenSu, AllenSu, AllenSu, 周五]
// replaceRange 用某一数组替换指定索引范围内的所有元素(含头不含尾)
List<String> l1 = ["周一", "周二", "周三"];
l1.replaceRange(1, 2, ["周四", "周五", "周六", "周日"]);
print(l1); // [周一, 周四, 周五, 周六, 周日, 周三]
List<String> l2 = ["周一", "周二", "周三", "周四", "周五"];
l2.replaceRange(0, 4, ["周六", "周日"]);
print(l2); // [周六, 周日, 周五]
// setRange 范围替换数组中的值(含头不含尾)
List<String> l1 = ["11", "22", "33"];
List<String> l2 = ["aa", "bb", "cc"];
l1.setRange(0, 2, l2); // 用 l2 数组中索引为 0 1 位置处元素的值,替换掉 l1 数组中索引 0 1 位置处元素的值
print(l1); // [aa, bb, 33]
// setAll 从指定索引位置开始,使用第二个数组内的元素依次替换掉第一个数组中的元素
List<String> l1 = ["周一", "周二", "周三", "周四"];
List<String> l2 = ["周五", "周六", "周日"];
l1.setAll(1, l2);
print(l1); // [周一, 周五, 周六, 周日]
// 注意: index + l2.length <= l1.length ,否则会报错。
查
方法名 | 作用 |
---|---|
forEach | 遍历数组中的元素 |
map | 遍历数组中的所有元素,可以对元素进行处理,并返回新的 Iterable |
elementAt | 获取指定索引位置处的元素 |
contains | 判断数组中是否含有指定元素 |
indexOf | 获取指定元素在数组中的索引 |
lastIndexOf | 从后向前查找指定元素在数组中的索引 |
indexWhere | 返回第一个满足条件的元素的索引 |
lastIndexWhere | 从后向前找,返回第一个满足条件的元素的索引 |
where | 根据指定条件,函数筛选每个元素,符合条件的元素组成一个新的 Iterable |
firstWhere | 返回第一个满足条件的元素 |
indexWhere | 返回第一个满足条件的元素的索引 |
lastIndexWhere | 从后向前找,返回第一个满足条件的元素的索引 |
where | 根据指定条件,函数筛选每个元素,符合条件的元素组成一个新的 Iterable |
firstWhere | 返回第一个满足条件的元素 |
every | 判断数组中是否每个元素都满足指定的条件 |
take | 从索引 0 位置处,取指定个数的元素 |
takeWhile | 从索引 0 位置处,查询满足指定条件的元素,直到出现第一个不符合条件的元素,然后返回前面符合条件的元素 |
skip | 跳过指定个数的元素,返回后面的元素 |
skipWhile | 根据指定条件,找到第一个不符合条件的元素,然后将该元素后面的所有元素返回 |
sublist | 从指定索引处截取数组 |
getRange | 截取指定索引范围内的元素 |
whereType | 从混合类型的数组中,筛选出指定类型的元素 |
// forEach 遍历数组中的元素
List<int> l1 = [8, 12, 4, 1];
l1.forEach((e) => print(e));
// 8 12 4 1
// map 遍历数组中的所有元素,可以对元素进行处理,并返回新的 Iterable
List<int> l1 = [8, 12, 4, 6, 22, 34, 10];
Iterable<bool> l2 = l1.map((e) => e > 10);
print(l2);
// (false, true, false, false, true, true, false)
Iterable<String> l3 = l1.map((e) => e > 10 ? "大" : "小");
print(l3);
// (小, 大, 小, 小, 大, 大, 小)
Iterable<num> l4 = l1.map((e) => e > 12 ? e / 2 : e * 2);
print(l4);
// (16, 24, 8, 12, 11.0, 17.0, 20)
// elementAt 获取指定索引位置处的元素 查看更多
List<String> l1 = ["周一", "周二", "周三", "周四"];
String str = l1.elementAt(2);
print(str); // 周三
// contains 判断数组中是否含有指定元素 查看更多
List<String> l1 = ["周一", "周二", "周三", "周四"];
bool a = l1.contains("周一");
bool b = l1.contains("周日");
print(a); // true
print(b); // false
// indexOf 获取指定元素在数组中的索引 查看更多
List<String> l1 = ["周一", "周二", "周三", "周四", "周三"];
int a = l1.indexOf("周三"); // 获取数组中第一次出现"周三"元素的索引
int b = l1.indexOf("周三", 3); // 从索引为3开始,查找第一次出现"周三"元素的索引
int c = l1.indexOf("周日");
print(a); // 2
print(b); // 4
print(c); // -1,数组中不存在指定元素,返回 -1
// lastIndexOf 从后向前查找指定元素在数组中的索引 查看更多
List<String> l1 = ["周一", "周二", "周三", "周四", "周三"];
int a = l1.lastIndexOf("周三");
int b = l1.lastIndexOf("周三", 3);
int c = l1.lastIndexOf("周日");
print(a); // 4
print(b); // 2
print(c); // -1
// indexWhere 返回第一个满足条件的元素的索引 查看更多
List<String> l1 = ["周一", "周二", "周三", "周四", "周三"];
int a = l1.indexWhere((e) => e == "周三");
print(a); // 2
// lastIndexWhere 从后向前找,返回第一个满足条件的元素的索引 查看更多
List<String> l1 = ["周一", "周二", "周三", "周四", "周三"];
int a = l1.lastIndexWhere((e) => e == "周三");
print(a); // 4
// where 根据指定条件,函数筛选每个元素,符合条件的元素组成一个新的 Iterable 查看更多
List<int> l1 = [8, 12, 4, 1, 17, 33, 10];
Iterable<int> l2 = l1.where((e) => e > 10);
print(l2); // (12, 17, 33)
List<int> l3 = l1.where((e) => e >= 10).toList();
print(l3); // [12, 17, 33]
// firstWhere 返回第一个满足条件的元素 查看更多
List<int> l1 = [8, 12, 4, 1, 17, 33, 10];
int a = l1.firstWhere((e) => e > 10);
print(a); // 12
// lastWhere 从后向前查找第一个满足条件的元素 查看更多
List<int> l1 = [8, 12, 4, 1, 17, 33, 10];
int a = l1.lastWhere((e) => e > 10);
print(a); // 33
// singleWhere 获取满足指定条件的唯一元素 查看更多
List<int> l1 = [8, 12, 4, 1, 17, 33, 10];
int a = l1.singleWhere((e) => e > 30);
int b = l1.singleWhere((e) => e > 33, orElse: () => -1);
int c = l1.singleWhere((e) => e > 10, orElse: () => null);
print(a); // 33
print(b); // -1。数组中没有满足条件的元素,返回 orElse 方法指定的返回值(-1是自己填的,你也可以设置为其它值)
print(c); // 报错。当数组中有多个满足条件的元素时,即使你设置了 orElse 的返回值,用 singleWhere 也会报错
// retainWhere 保留满足条件的元素(改变了原数组) 查看更多
List<int> l1 = [8, 12, 4, 1, 17, 33, 10];
l1.retainWhere((e) => e > 10);
print(l1); // [12, 17, 33]
// any 判断数组中是否有满足指定条件的元素 查看更多
List<int> l1 = [8, 12, 4, 1, 17, 33, 10];
bool a = l1.any((e) => e > 30);
print(a); // true
// every 判断数组中是否每个元素都满足指定的条件 查看更多
List<int> l1 = [8, 12, 4, 1, 17, 33, 10];
bool a = l1.every((e) => e > 1);
print(a); // false
main() {
List myList = [1, 3, 4, 5, 7, 8, 9];
var newList = myList.where((value) {
return value > 5;
});
print(newList.toList());
List myList = [1, 3, 4, 5, 7, 8, 9];
var f = myList.any((value) {
//只要集合里面有满足条件的就返回true
return value > 5;
});
print(f);
List myList = [1, 3, 4, 5, 7, 8, 9];
var f = myList.every((value) {
//每一个都满足条件返回true 否则返回false
return value > 5;
});
print(f);
}
// take 从索引 0 位置处,取指定个数的元素 查看更多
List<int> l1 = [8, 12, 4, 1, 17, 33, 10];
Iterable<int> l2 = l1.take(3);
print(l2); // (8, 12, 4)
// takeWhile 从索引 0 位置处,查询满足指定条件的元素,直到出现第一个不符合条件的元素,然后返回前面符合条件的元素 查看更多
List<int> l1 = [8, 12, 4, 1, 17, 33, 10];
Iterable<int> l2 = l1.takeWhile((e) => e > 1);
print(l2); // (8, 12, 4)
// skip 跳过指定个数的元素,返回后面的元素
List<int> l1 = [8, 12, 4, 1, 17, 33, 10];
Iterable<int> l2 = l1.skip(4);
print(l2); // (17, 33, 10)
// skipWhile 根据指定条件,找到第一个不符合条件的元素,然后将该元素后面的所有元素返回
List<int> l1 = [8, 12, 4, 1, 17, 33, 10];
Iterable<int> l2 = l1.skipWhile((e) => e < 17);
print(l2); // (17, 33, 10)
// sublist 从指定索引处截取数组
List<int> l1 = [8, 12, 4, 1, 17, 33, 10];
List<int> l2 = l1.sublist(5);
print(l2); // [33, 10]
List<int> l3 = l1.sublist(2, 5);
print(l3); // [4, 1, 17] 含头不含尾
//getRange 截取指定索引范围内的元素
List<int> l1 = [8, 12, 4, 1, 17, 33, 10];
Iterable<int> l2 = l1.getRange(2,5);
print(l2); // (4, 1, 17)
//whereType 从混合类型的数组中,筛选出指定类型的元素
List l1 = ["a", 15, "b", false, true, 20, "c",{"name":"AllenSu"}];
Iterable<String> l2 = l1.whereType();
Iterable<int> l3 = l1.whereType();
Iterable<bool> l4 = l1.whereType();
Iterable<Map> l5 = l1.whereType();
print(l2); // (a, b, c)
print(l3); // (15, 20)
print(l4); // (false, true)
print(l5); // ({name: AllenSu})
3.set类型
Set
表示对象的集合,每个对象只能出现一次。最主要的功能就是去除数组重复内容。
1)定义
Set 集合名 = Set.from([元素一, 元素二, ...]);
2)属性
Set 中的常用属性有:
属性 | 描述 |
---|---|
first | 返回 Set 的第一个元素 |
last | 返回 Set 的最后一个元素 |
length | 返回 Set 的元素个数 |
isEmpty | 判断 Set 是否为空 |
isNotEmpty | 判断 Set 是否不为空 |
iterator | 返回迭代器对象,用于遍历集合 |
void main() {
Set set = Set.from(['Jimmy', 'Ivy']);
print(set.first); // Jimmy
print(set.last); // Ivy
print(set.length); // 2
print(set.isEmpty); // false
print(set.isNotEmpty); // true
print(set.iterator); // Instance of '_CompactIterator<dynamic>'
}
3)方法
Set 中的常用方法有:
方法 | 描述 |
---|---|
add | 添加一个元素 |
addAll | 添加一些元素 |
toString | 转换字符串形式 |
join | 以指定的字符串连接,以字符串形式输出 |
contains | 集合中是否包含指定元素 |
containsAll | 集合中是否包含指定一些元素 |
elementAt(index) | 根据索引返回集合的元素 |
join | 以指定的字符串连接,以字符串形式输出 |
remove | 删除指定的元素 |
removeAll | 删除指定的一些元素 |
clear | 删除所有元素 |
void main() {
Set set = Set.from([]);
set.add('Jimmy');
print(set.toString()); // {Jimmy}
set.addAll(['Ivy', 'Kimmy']);
print(set.join('-')); // Jimmy-Ivy-Kimmy
print(set.contains('Timmy')); // false
print(set.containsAll(['Jimmy', 'Kimmy'])); // true
print(set.elementAt(1)); // Ivy
set.remove('Kimmy');
print(set); // {Jimmy, Ivy}
set.removeAll(['Jimmy', 'Anonymous']);
print(set); // {Ivy}
set.clear();
print(set); // {}
}
Set 遍历:
Set 集合遍历的方法有两种:
for...in 循环
调用 toList 方法返回一个 List 对象,再用 List 对象的遍历方法操作...
void main() {
Set set = Set.from(['Jimmy', 'Ivy']);
for(var item in set) {
print(item);
// Jimmy
// Ivy
}
set.toList().forEach((item){
print(item);
// Jimmy
// Ivy
});
}
去重
void main(){
List myList=['香蕉','苹果','西瓜','香蕉','苹果','香蕉','苹果'];
var s=new Set();
s.addAll(myList);
print(s);
// {香蕉, 苹果, 西瓜}
print(s.toList());
// [香蕉, 苹果, 西瓜]
}
4.Map类型
映射(Map)又称为关联数组,映射(Maps)是无序的键值对,相当于Java中的HashMap
1)定义
// 1.通过字面量创建Map,key必须加引号
var gifts = {
'first': 'partridge',
'second': 'turtledoves',
'fifth': 'golden rings'
};
// 2.使用Map类的构造函数创建对象
var pic = new Map();
// 往Map中添加键值对
pic['first'] = 'partridge';
pic['second'] = 'turtledoves';
pic['fifth'] = 'goden rings';
// 3.获取Map的长度
print(pic.Tength);
// 4.查找Map
pirnt(pic["first"]);
print(pic["four"]); // 键不存在则返回 null
var persion={
"name":"Dart",
"age":"8"
};
print(persion); //输出 {name: Dart, age: 8}
print(persion['name']); //输出 Dart
print(persion['age']); //输出 8
var persion1=new Map();
persion1["name"]="张三";
persion1["age"]="9";
print(persion1); //输出 {name: 张三, age: 9}
print(persion1['name']); //输出 张三
print(persion1['age']); //输出 9
2)属性
通用属性:
forEach
map
where
any
every
常用属性:
keys 获取所有的key值
values 获取所有的value值
isEmpty 是否为空
isNotEmpty 是否不为空
Map person = {"name": "张三", "age": 20, "sex": "男"};
print(person.keys.toList());
// [name, age, sex]
print(person.values.toList());
// [张三, 20, 男]
print(person.isEmpty);
// false
print(person.isNotEmpty);
// true
3)方法
remove(key) 删除指定key的数据
addAll({...}) 合并映射 给映射内增加属性
containsValue 查看映射内的值 返回true/false
Map person = {"name": "张三", "age": 20, "sex": "男"};
person.addAll({
"work": ['敲代码', '送外卖'],
"height": 160
});
print(person);
person.remove("sex");
print(person);
5.总结
1)类型转换
- Number 转换为 String 使用toString();
- String转换为 Number 使用parse();
int.parse()
//将字符串转换为整型
String str='111';
var myNum=int.parse(str); //输出 111
toString()
//将整型转换为字符串
var myNum = 18;
var str = myNum.toString();
print(str is String); //输出 true
//注意转换时报异常
String str = ''; //字符串为空,转换为整型会报错
try {
var myNum = int.parse(str);
print("myNum");
} catch (err){
print("转换错误");
}
tostringAsFixed(num)
// String 转 int
var one = int.parse('1' );
// string 转 double
var onePointone = double.parse('1.1');
// int 转 String
String oneAsStr = 1.toString() ;
// double 转 string
String piAsStr = 3.14159.tostringAsFixed(2); // 保留两位3.14
// Dart也支持整数位操作,<<、>>、&、|
print((3 << 1) == 6); // 0011 << 1 == 0110
print((3 >> 1) == 1); // 0011 >> 1 == 0001
print((3 4) == 7); // 0011 0100 == 0111
2)通用属性
forEach
// 以下结果等价
for(var item in myList){
print(item);
}
myList.forEach((value){
print("$value");
});
var s = new Set();
s.addAll([1, 222, 333]);
s.forEach((value) => print(value));
// 1
// 222
// 333
Map person = {"name": "张三", "age": 20};
person.forEach((key, value) {
print("$key---$value");
});
// name---张三
// age---20
map
// 以下结果等价
List myList = [1, 3, 4];
List newList = [];
for (var i = 0; i < myList.length; i++) {
newList.add(myList[i] * 2);
}
print(newList);
// [2, 6, 8]
List myList=[1,3,4];
var newList=myList.map((value){
return value*2;
});
print(newList.toList());
// [2, 6, 8]
where
List myList = [1, 3, 4, 5, 7, 8, 9];
var newList = myList.where((value) {
return value > 5;
});
print(newList.toList());
// [7, 8, 9]
any,every
var f1 = myList.any((value) {
//只要集合里面有满足条件的就返回true
return value > 5;
});
print(f1);
// true
var f2 = myList.every((value) {
//每一个都满足条件返回true 否则返回false
return value > 5;
});
print(f2);
// false
三、运算符
- 算数运算符
- 关系运算符
- 逻辑运算符
- 赋值运算符
- 条件表达式
- 类型转换
1.算数运算符
Dart中又多出了一个整除运算符~/
,与普通除号的区别是将相除后的结果取整返回。
int a=5;
int b=4;
print(a+b); //加
print(a-b); //减
print(a*b); //乘
print(a/b); //除
print(a%b); //取余
print(a~/b); //取整
9
1
20
1.25
1
1
2.关系运算符
int a=5;
int b=4;
print(a==b); //是否相等
print(a!=b); //是否不相等
print(a>b); //是否大于
print(a<b); //是否小于
print(a>=b); //是否大于或者等于
print(a<=b); //是否小于或者等于
false
true
true
false
true
false
3.逻辑运算符
1)!
var b =false;
print(!b); //输出为true
2)&&
var a = true;
var b = false;
print(b && a); // 输出false
3)||
var a = true;
var b = false;
print(b || a); // 输出true
4.赋值运算符
1)=
int b = 6;
2)??=
int b;
b??=6; //当 b在这之前没有被赋值,则在这行代码中会被赋值
3)复合赋值
int b = 6;
b += 10;
print(b); //输出 16
5.类型判定运算符
以下是Dart增加的类型相关的运算符。
操作符 | 解释 |
---|---|
as | 用于类型转换 |
is | 如果对象是指定的类型就返回 True |
is! | 如果对象不是指定的类型返回 True |
当 obj 实现了 T 的接口时, obj is T 才是 true。类似于Java中的instanceof。
Dart中使用 as 操作符把对象转换为特定的类型,如无法转换则会抛出异常,因此在转换前最好使用is运算符进行检测。
// 将p转换为Person类型再操作
(p as Person) .name = 'Bruce':
1)as
Dart中使用 as 操作符把对象转换为特定的类型,如无法转换则会抛出异常,因此在转换前最好使用is运算符进行检测。
// 将p转换为Person类型再操作
(p as Person) .name = 'Bruce'
2)is
var str = '111';
if (str is String) {
print("str is String type");
} else if (str is int) {
print("str is int type");
} else {
print("str is other type");
}
}
// 结果 : 输出 str is String type
5.条件表达式
既三目运算符
解释:当等号=后的变量为true时,给变量赋值 : 前面的值,当flag为false时,给 变量赋值 : 后面的值
bool flag = true;
String b = flag ? "I am a boy " : " I am a girl";
print(b);
结果 : I am a boy
解释:flag 为true,赋值I am a boy
6.非空条件判断符
既??运算符
解释:当a为null时,赋值??符号后的10给a,然后将a赋值给b.
当a不为null时,直接将a赋值给b
var a;
var b = a ?? 10;
print(b); // 输出10
var a=20;
var b = a ?? 10;
print(b); //输出20
7.级联运算符
见函数篇
8.空运算符
1)?
可将不为空的数据类型设置为空
main() {
String? username = "张三"; // String? 表示username是一个可空类型
username = null;
print(username);
int? a = 123; // int? 表示a是一个可空类型
a = null;
print(a);
List<String>? l1 = ["张三", "李四", "王五"];
l1 = null;
print(l1);
}
2)!
void printLength1(String? str) {
if (str != null) {
print(str.length);
}else{
print("str is null");
}
}
void printLength2(String? str) {
try {
print(str!.length);
} catch (e) {
print("str is null");
}
}
main(){
printLength1("abc");
// 3
printLength2("abc");
// 3
printLength1(null);
// str is null
printLength2(null);
// str is null
}
四、分支循环语句
1.分支语句
1)if else
条件判断语句
var b1=true;
if(b1){
print('true');
}else{
print('false');
}
true
2)switch case
var sex = "boy";
switch(sex){
case "boy" :
print("boy");
break;
case "girl":
print("girl");
break;
default:
print("传入的参数错误");
break;
}
boy
2.循环语句
1)for循环
for (int i = 0; i < 5; i++) {
print(i);
}
0
1
2
3
4
for…in
var myList = ['Java','JavaScript','Dart'];
// for...in...循环,类似Java中的增强for
for (var it in myList ){
print(it);
}
forEach
var myList = ['Java','JavaScript','Dart'];
// forEach循环。其参数为一个Function对象,这里传入一个匿名函数
myList.forEach((var it){
print(it);
});
//可以使用匿名箭头函数简写
myList.forEach((it) => print(it));
main() {
var myMap = {'zhangsan': '201901', 'lisi': '201902', 'wangwu': '201902'};
// forEach遍历Map
myMap.forEach((k, v) => print("$k : $v"));
// 根据键获取值来遍历。通过keys返回Map中所有键的集合
for (var k in myMap.keys) {
print("$k : ${myMap[k]}");
}
}
2)while循环
var i = 0;
while (i < 5) {
print(i);
i++;
}
0
1
2
3
4
do while: 先进行操作再判断条件
do {
print(i);
i++;
} while (i < 5);
0
1
2
3
4
3)break和continue
break :
- 在switch语句中跳出switch结构
- 在循环语句中跳出当前循环语句(注意只能向外跳出一层循环)
continue:
- 只能在循环语句中使用
- 跳出当前的此次循环,继续进行下一次循环
五、异常处理
针对不同异常进行不同处理,可以使用try...on
处理异常,finally
是可选的,用于最后的处理。
void main() {
try {
// 使除数为0
print(11 ~/ 0);
} on UnsupportedError {
print("除数为0");
} on Exception {
print("Exception");
} finally {
print("finally");
}
}
不关心具体异常,只想捕获,避免异常继续传递,则可以使用try...catch
处理
如果想获取更多异常信息,可以使用两个参数的catch
,第二个参数是异常的调用栈信息
try {
print(11~/0);}
catch(e,s){
print(s);
}
;
break;
case “girl”:
print(“girl”);
break;
default:
print(“传入的参数错误”);
break;
}
~~~dart
boy
2.循环语句
1)for循环
for (int i = 0; i < 5; i++) {
print(i);
}
0
1
2
3
4
for…in
var myList = ['Java','JavaScript','Dart'];
// for...in...循环,类似Java中的增强for
for (var it in myList ){
print(it);
}
forEach
var myList = ['Java','JavaScript','Dart'];
// forEach循环。其参数为一个Function对象,这里传入一个匿名函数
myList.forEach((var it){
print(it);
});
//可以使用匿名箭头函数简写
myList.forEach((it) => print(it));
main() {
var myMap = {'zhangsan': '201901', 'lisi': '201902', 'wangwu': '201902'};
// forEach遍历Map
myMap.forEach((k, v) => print("$k : $v"));
// 根据键获取值来遍历。通过keys返回Map中所有键的集合
for (var k in myMap.keys) {
print("$k : ${myMap[k]}");
}
}
2)while循环
var i = 0;
while (i < 5) {
print(i);
i++;
}
0
1
2
3
4
do while: 先进行操作再判断条件
do {
print(i);
i++;
} while (i < 5);
0
1
2
3
4
3)break和continue
break :
- 在switch语句中跳出switch结构
- 在循环语句中跳出当前循环语句(注意只能向外跳出一层循环)
continue:
- 只能在循环语句中使用
- 跳出当前的此次循环,继续进行下一次循环
五、异常处理
针对不同异常进行不同处理,可以使用try...on
处理异常,finally
是可选的,用于最后的处理。
void main() {
try {
// 使除数为0
print(11 ~/ 0);
} on UnsupportedError {
print("除数为0");
} on Exception {
print("Exception");
} finally {
print("finally");
}
}
不关心具体异常,只想捕获,避免异常继续传递,则可以使用try...catch
处理
如果想获取更多异常信息,可以使用两个参数的catch
,第二个参数是异常的调用栈信息
try {
print(11~/0);}
catch(e,s){
print(s);
}