目录
一、mac 配置Flutter运行环境
二、dart 语言的特性
三、开搞
1.var.final.const
var
2.Dart 数据类型
3.1 String书写格式
3.2 dart 中 String操作
3.3 dart 中 String操作
4.list
5.Map
6.运算符
7.1 dart中的方法,箭头函数
7.2 dart中的方法可选参数
7.3 dart中的方法作为参数传递
7.4 闭包
1.配置镜像
下载flutter SDK国内访问Flutter有时可能会受到限制,将如下环境变量加入到用户环境变量中:
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
2.获取Flutter SDKhttps://docs.flutter.dev/development/tools/sdk/releases?tab=windows#macos下载完成后提添加环境变量# Flutter 配置
export FLUTTER=/Users/lsp/flutter/bin
export PATH=$FLUTTER:$PATH
3.安装Android Studio,或者 VS code安装Flutter和Dart插件
需要安装两个插件:
Flutter插件: 支持Flutter开发工作流 (运行、调试、热重载等).
Dart插件: 提供代码分析 (输入代码时进行验证、代码补全等).
要安装这些:
启动Android Studio.
打开插件首选项 (Preferences>Plugins on macOS, File>Settings>Plugins on Windows & Linux).
选择 Browse repositories…, 选择 Flutter 插件并点击 install.
重启Android Studio后插件生效
1. Dart 同时支持 JIT(Just In Time,即时编译)和 AOT(Ahead of Time,运行前编译)
JIT 在运行时即时编译,一句一句边翻译边运行,如JavaScript、python等,事实上,所有脚本语言都支持JIT模式。
AOT 即提前编译,在执行前全部被翻译为机器码,运行速度快、执行性能好,但每次执行前都需要提前编译,开发测试效率低。典型代表是用C/C++开发的应用,它们必须在执行前编译成机器码。
2. 所有变量的值都是对象,也就是类的实例。甚至数字、函数和null也都是对象,都继承自Object类。
3. Dart可以在没有锁的情况下进行对象分配和垃圾回收。Dart开发团队的很多成员都是来自Chrome团队的,像JavaScript一样,Dart避免了抢占式调度和共享内存,大多数支持并发执行线程的计算机语言(Java、Kotlin、Swift)都使用抢占式来切换线程,抢占就会产生竞态条件,竞态条件很有可能导致严重错误,如应用程序崩溃导致数据丢失等等,一般解决竞态条件使用锁来保护,但是锁本身可能导致卡顿,也有可能产生死锁,而Dart针对这个问题,采取了isolate方法来解决,那么Dart是单线程,因为它天然不存在资源竞争和状态同步的问题。这就意味着,一旦某个函数开始执行,就将执行到这个函数结束,而不会被其他 Dart 代码打断。Dart 中并没有线程,只有 Isolate(隔离区)。Isolates 之间不会共享内存,就像几个运行在不同进程中的 worker,通过事件循环(Event Looper)在事件队列(Event Queue)上传递消息通信。
* dart 语言动态类型,类型是可选的
* 可以使用var 声明变量,可以赋值不同的类型
* var 声明的变量没有初始化 为null
final
* final 只能赋值一次的(变量)!
*可以声明,今后不会改变的变量
* 在使用之前必须赋值
const
* const 常量声明 再声明时 必须有初始值!
* const声明之后,不允许改变
/**
* dart 语言动态类型,类型是可选的
*可以使用var 声明变量,可以赋值不同的类型
* var 声明的变量没有初始化 为null
* */
void varDemo(){
var name = '2';
String name1 = "name1";
print(int.parse(name));
print(name1);
var bbb;
bbb = 3;
bbb = '222';
print(bbb);
/**
* final 只能赋值一次的(变量)!
*可以声明,今后不会改变的变量
* 在使用之前必须赋值
* const 常量声明 再声明时 必须有初始值!
*/
final c;
c = 'hello';
print(c);
const dd = 55;
print(dd);
//
}
Number
* num类型在初始化时候需要先赋值
* 赋值完成后可以改变Int/Double类型
int 与double 继承自Number
* int类型 无法赋值double类型
* double类型可以赋值 int值(会将int类型转成double类型)
Number 运算符
* 算数运算符号 + - * / %
* dart 特有的 ~/(取整)
Q: /、~/ 区别
A: c/a 有小数|c ~/ a 取除的整数
/**
* Dart 数据类型
* 数值型 Number int & double
* 字符串
* bool
* 列表 - list
* 字典(键值对) - Map
* */
/**
* num类型在初始化时候,必须先赋值
* 可以赋值不同类型
* */
void numDemo(){
num a = 1;
a = 2.9;
print(a);
/**
* int类型 无法赋值double类型
* double类型 可以赋值 int类型,会将int类型转成double类型
* */
int b = 9;
print(b);
double c = 9.23333;
c = 10;
print(c);//10.0
/**
* 算数运算符号 + - * / %
* dart 特有的 ~/(取整)
* c/a 有小数
* c ~/ a 取除的整数
* */
int x = 10;
int y = 3;
print(x ~/ y);//3
print(x/y);//3.3333333333333335
print(y ~/ x);//0
print(y/x);//0.3
}
* 使用单引号或者双引号
* 使用双引号或者三个引号创建多行字符串
*获取字符串的第n个字符串,方法像数组获取一样,使用下标直接获取
* dart中使用 ${ }承接
* 可以在其中进行变量的运算
示例:
/**
* 使用单引号或者双引号
* 使用双引号或者三个引号创建多行字符串
*
*获取字符串的第n个字符串,方法像数组获取一样,使用下标直接获取
*
*打印,
* */
void stringDemo(){
String str1 = 'Hello';
String str2 = "World";
print(str1 + str2);
String str3 = "Hello" "你好" "萨瓦迪卡";
print(str3);
String str4 = '''hello
你好
再见''';
print(str4);
String str = '你好,你在哪';
print(str[0]);//
print(str[1]);//
print(str * 2);//你好,你在哪你好,你在哪
int a = 5;
int b = 4;
int c = a + b;
String sss = 'a+b = ${a + b}';
print('a + b = ${a + b}');
print('a + b = $c');
String string = 'lisp\n哈哈哈';
print(string);
String string2 = r'lisp\n哈哈哈';
print(string2);
}
*String 与 number 转换
// 使用 try catch 防止程序崩溃
* Number 转 String
示例:
/**
* string 转int
* */
switchStype(){
String age = '20';
try{
int age1 = int.parse(age);
print(age1);
}catch(err){
print(0);
}
// number 转 string
var myNum = 12;
var str = myNum.toString();
print(str is String);
}
* dart中的列表 分为 可变与不可变
* 可变列表
var list = [1,2,3];
* 不可变列表,在开头说过,const 声明常量在赋值后不允许改变。const 加在了元素前,指的是,数组中的元素不可变,元素不可变,列表就不可变。
var list = const[1,2,3];
dart 数组中可以存放不同的数据类型
示例:
/**
* dart中的列表 分为 可变与不可变
* 可变
* var list = [1,2,3];
* 不可变(const 加在了元素前,指的是,数组中的元素不可变)
* var list = const[1,2,3];
* 不可变数组,元素不能更改
* dart 数组中存放不同的数据类型
* */
void listDemo(){
var list = [1,2,3];
var list1 = const[1,2,3];
var list3 = [99,"你好",8.3];
print(list3[2]);// 通过下标取值
list3.add(4);//增加
list3.remove(99);//删除
list3.insert(1, 99999);//插入
list3.clear();//清空数组
print(list3);
var list4 = [1,2,5,9,88,2];
list4.sort();//由低到高排序,数组内类型不一致报错、【1 2 2 5 9 88】
print(list4.sublist(2,5));//从第几位截取,包前不包后 [2, 5, 9]
}
* 可变Map
* 与list同理,不可变的Map,在键值对之前加入const
* 不可变Map,键值对不能更改
示例:
void mapDemo(){
/**
* dart Map
* 可变Map
* var json = {"one":"lisp","two":"fanglq"};
* 不可变的Map
* var json1 = const{"one":"lisp","two":"fanglq"};
* */
var json = const {1:"lisp","two":"fanglq"};
print(json[1]);//获取value
print(json["two"]);//获取value
json[1] = "guibao";//更改元素
json.remove("1");//根据key 删除键值对
print(json.length);//查看键值对数量
print(json.values);//查看values
print(json.keys);//查看key
//数组可通过 asMap 直接转成map对象。以下标为key。数组元素为value的map对象
var list = ["lisp","fanglq","haogb"];
Map map = list.asMap();
print(map);
}
PS *数组可通过 asMap方法 直接转成map对象。以下标为key。数组元素为value的map对象
示例:
var list = ["lisp","fanglq","haogb"];
Map map = list.asMap();
print(map);
* dart 中比较特殊对运算符
* 赋值运算 ??=
* 条件表达式 ?? 如果左边的为空,那赋值为
如果b 有值 返回b,如果b为null。返回a
示例:
void operatorDemo(){
/**
* dart 中比较特殊对运算符
* 赋值运算 ??=
* 条件表达式 ??
*
* */
var a;
a ??= 10; // 如果a 为null.赋值
a ??= 5; //如果 a 有值 直接返回
print(a); //5
var b;
b = 15;
print( b ??= a);
}
* dart 中的方法也是一个对象
* 返回值和参数类型可以省略
* 当方法的执行语句只有一句的时候,可以使用箭头函数 => 表达式
* 只要 一句话能放的下,就可以使用箭头函数
示例:
/**
* dart 中的方法也是一个对象
* 返回值和参数类型可以省略
* 当方法的执行语句只有一句的时候,可以使用箭头函数 => 表达式
* 只要 一句话能放的下,就能使用箭头函数
* */
void funcDemo1() => arrowFunc();
void arrowFunc(){
print('箭头函数');
}
//forEach
void listEach(){
List list = [8,9,2,32,16];
list.forEach((element) {
print(element);
});
print('-------------------------');
list.forEach((element) => print(element));
print('-------------------------');
print(sum(10,20));
print(sum1(1, 4));
}
//* 返回值和参数类型可以省略
// int sum(int a, int b){
// return a + b;
// }
//容易蒙蔽不建议写
sum(a,b) => a+b;
//箭头函数可以加入三母运算
sum1(a,b) => a==1 ? a+b : a-b;
* 可选参数上
*可以只选择其中一个赋值
* 可以使用{ } 赋值时候,必须带上参数名字,但是不用按照顺序
* 因为可选参数,隐式默认值为null,带上int 类型,参数就不能为null。 因为int 不能为null
* 可选参数,也可以使用 [ ]
* 不需要带形参名字,必须按照顺序赋值。
* 赋值时候,后面可以空着,但前面不行
void optionalParameters(){
print(sum2(5,b: 3,c: 2));
print(sum3(3,4,1));
}
/**
* 可选参数:
*可以只选择其中一个赋值
* 可以使用{} 赋值时候,必须带上参数名字,但是不用按照顺序
* 因为可选参数,隐士默认值为null,带上int 类型,参数就不能为null。 因为int 不能为null
* // print(sum2(5,b: 3,c: 2));
*
* */
sum2(int a,{int? b, int? c}){// int? 告诉编译器,我处理了后面为空的情况,不要管我了,
b ??= 1;
c ??= 2;
return a + b + c;
}
/**
* 可选参数,可以使用 []
* 可以使用 []
* 不需要带形参名字,必须按照顺序赋值。
* 赋值时候,后面可以空着,但前面不行
* */
sum3(int a,[int b = 2,int c = 3]){
return a + b + c;
}
* 函数可以作为对象赋值给一个变量
* 类似block,作为参数传递
/**
* 函数可以作为对象赋值给一个变量
* 类似block,作为参数传递
*/
void funcObjDemo(){
var list = [1,2,3,4];
list.forEach(print);//系统
list.forEach(printElement);//定义void
forEachElement(list,printElement);//全部定义
}
int b = 0;
void printElement(var ele){
b++;
print('第$b个 = $ele');
}
// forEachElement(list,print);
void forEachElement(List list,void func(var element)){
for(var e in list) func(e);
}
* 匿名函数
* 作为参数,发挥作用 函数式编程
* 类似于block
void anonymousDemo(){
var func = (){
print('匿名方法');
};
func();
//立即执行方法函数
(){
print('匿名方法立即执行');
}();
var list = [1,2,3,4];
// forEachElement(list,printElement);
// 转化
forEachElement(list,(var ele){
b++;
print('第$b个 = $ele');
});
}
* 闭包 closure
* 定义在函数里面的函数,叫做闭包
* 闭包也是个对象
* 作用:可以访问外部函数的局部变量
void closureDemo(){
print('1111');
var func = funA();
func();
func();
func();
func();
func();
var func2 = funA();// count 全新的栈内存
func2();
func2();
func2();
func2();
func2();
print('222222222');
}
funA(){
int count = 0;
return () => print(count++);//这个匿名函数就是个闭包,访问的外部变量并不会释放
}