Flutter & Dart自学笔记——Dart语言
Dart语言
变量
-
var 变量名 = 值/表达式
// 声明时需要赋值,通过变量值来确定数据类型
// 声明时无法赋值,则可使用late var来声明,但在使用前要赋值
常量
-
const 属性名 = 值/表达式
// 编译时确定,声明后不允许修改
// 如果值是表达式,则表达式中不允许有变量
// 比如圆周率const pi = 3.1415926;
-
final 属性名 = 值/表达式
// 运行时确定,不允许修改
// 比如当前时间 final time = DataTime.now;
类型
-
String 属性名 = '文本' /
String 属性名 = '文本$变量名' /
String 属性名 = '文本${变量名/表达式}' /
// 文本类型
// 引号可以单引号或双引号
// 模板字符串的时候表达式必须${},变量名也建议使用
-
int / num / double 属性名 = 数值
// 数字类型,int 整型,num 可整型可小数,double 小数
// double和int间不能直接赋值,可使用方法toInt,toDouble转换
// num不能给double直接赋值,不能给int直接赋值
-
bool 属性名 = true / false
// 布尔类型,表示为true或false
-
List 属性名 = [ 值, ..., 值]
// 列表类型
// 方法:
在尾部添加-add(内容)
在尾部添加列表-addAll(列表)
删除满足内容的第一个-remove(内容)
删除最后一个-removedLast()
删除索引范围内的数据-removeRange(start,end),其中end不包括在删除范围内
循环-forEach((item){})
是否都满足条件-every((item){ return 布尔值 })
算选出满足条件的数据-where((item){ return 布尔值 })
列表的长度(属性)-length
最后一个元素(属性)-last
第一个元素(属性)-first
是否为空(属性)-isEmpty
-
Map 属性名 = { key:value }
// 字典类型
// key、value是字符串的需要加引号
// 取值 属性名['key'],赋值 属性名['key'] = 值
// 方法:
循环-forEach(( key, value ){})
添加一个字典-addAll(字典)
是否包含某个key的-containsKey(key名称)
删除某个key和值-remove(key名称)
清空字典-clear()
动态类型
-
dynamic 属性名 = 值
// 允许变量类型在运行时自由改变,无编译检查,慎用
// 声明时字符串,后可赋值数字、bool等类类型
空安全机制
-
编译静态检查将运行时空指针提前暴露,减少线上崩溃
-
空安全操作符:
操作符 符号 作用 示例 可空类型 ? 声明可空变量 String? -> 允许String 或 null 安全访问 ?. 对象为null时跳过操作,返回null user?.name -> 若 user 为 null 则返回 null 非空断言 !. 开发者保证变量非空,否则运行时崩溃 name!.length -> 断言 name 非空 空合并 ?? 左侧为 null 时返回右侧默认值 name ?? "Guest" -> name 为 null 时返回"Guest"
运算符
-
算术运算符:
运算符 作用 + 加 - 减 * 乘 / 除 ~/ 整除 % 取余数 -
赋值运算符
运算符 作用 = 赋值操作 += 加等 a+=b 相当于 a = a+b -= 减等 a-=b 相当于 a = a-b *= 乘等 a * =b 相当于 a = a*b /= 除等 a/=b 相当于 a = a/b -
比较运算符
运算符 作用 == 两个值是否相等 != 两个值是否不等 > 左侧值是否大于右侧值 >= 左侧值是否大于等于右侧值 < 左侧值是否小于右侧值 <= 左侧值是否小于等于右侧值 -
逻辑运算符 // 对bool类型的值进行运算
运算符 作用 && 逻辑与 | | 逻辑或 ! 逻辑非
流程控制
-
if
// 单分支
if(表达式布尔值){}// 双分支
if(表达式布尔值){} else{}// 多分支
if(表达式布尔值){} else if(表达式布尔值){} ... else{} -
三元运算符
// 表达式(要求结果为布尔值) ? 结果1 : 结果2;
// 布尔值为true选结果1,false为结果2
//
print(score > 68 ?'及格' : '不及格'); -
switch/case
switch(变量){ case 值1: 逻辑1; break; case 值2: 逻辑2; break; default: 默认逻辑; -
while
while(条件){ 逻辑; }// 当条件满足时,逻辑一致执行,可使用break和continue来跳出循环。其中break是跳出while循环,continue是跳出当前迭代
-
for
for(int i=0; i<10; i++){ 逻辑; }// 在逻辑中可以使用break来跳出整个循环,使用continue来掏出当前迭代
函数
-
函数类型
// 有返回值的函数:具体类型 函数名称(){}
// 没有返回值的函数:void 函数名称(){}
// 返回值类型可省略,dart会自动推断类型为dynamic,但推荐指定返回值类型
-
函数参数分类
// 示例:
// 必传参数,不能为空,如String test (String a)
// 可选位置参数,位于必传参数之后,采用中括号包裹。如String test (String a, [String? b,...]),传递时按照顺序传递,适用于参数少且顺序固定时
// 可选命名参数,位于必传参数之后,采用大括号包裹。如String test (String a, {String? b,...}),传递时按照参数名:值的方式进行传递,无需关注顺序,适用于参数多且需明确含义时
-
匿名函数
// 可以声明一个没有名称的函数赋值给一个变量,进行调用
// Function 变量名 = (){}
// 两种使用方式 void main(List<String> args) { test(); // 直接调用 onTest(test); // 作为参数传递给函数,再调用 } Function test = () { print("测试"); } void onTest(Function callback) { callback(); } -
箭头函数
// 当一个函数体自由一行代码时,使用箭头函数编写
// 函数名() => 代码逻辑
// 使用箭头函数可以省略return关键字
void main(List<String> args) { print(add1(1,2)); print(add2(1,2)); } // 原方法 int add1(int a, int b) { return a+b } // 箭头函数方法 int add2(int a, int b) => a+b;
类
-
类class是面向对象编程的核心,类包括属性和方法
// 定义一个Person类,属性包括姓名、年龄、性别,方法包括学习
// 定义类 class Person {属性 方法}
// 示例化 Person 变量 = Person();
// 调用 变量.属性/方法()
void main(List<String> args) { Person p = Person(); p.name = "老高"; p.study(); } class Person { String name = ""; int age = 0; String sex = "男"; void study() { print("$name在学习"); } } -
构造函数:
// 默认构造函数、命名构造函数、构造函数的语法糖
-
默认构造函数:
// 定义 class 类名 { 类名(可选命名参数){ } } // 实例化 Person p = Person(属性:值)void main(List<String> args) { Person p = Person(name:"", age:"20", sex:"男"); p.study(); } class Person { String? name = ""; int? age = 0; String? sex = "男"; Person({String? name, int? age, String? sex}) { this.name = name; this.age = age; this.sex = sex; } void study() { print("$name在学习"); } } -
命名构造函数
// 构造函数可以采用命名的方式,返回一个示例化对象
// 定义 class 类名 { 类名.构造函数名(可选命名参数) } // 实例化 Person p = Person.构造函数名(属性:值)void main(List<String> args) { Person p = Person.createPerson(name:"", age:"20", sex:"男"); p.study(); } class Person { String? name = ""; int? age = 0; String? sex = "男"; Person.createPerson({String? name, int? age, String? sex}) { this.name = name; this.age = age; this.sex = sex; } void study() { print("$name在学习"); } } -
构造函数语法糖
// 同名构造函数(默认构造函数)、命名构造函数都支持简写写法
class 类名 { 类名({this.属性1,this.属性2}); 或 类名.命名函数({this.属性1,this.属性2}); }void main(List<String> args) { Person p1 = Person(name:"", age:"20", sex:"男"); Person p2 = Person.createPerson(name:"", age:"20", sex:"男"); p1.study(); p2.study(); } class Person { String? name = ""; int? age = 0; String? sex = "男"; Person({this.name, this.age, this.sex}); // 语法糖 Person.createPerson({this.name, this.age, this.sex}); // 语法糖 void study() { print("$name在学习"); } }
-
-
公有属性和私有属性
// 共有属性,提供自身或则其他外部文件和类使用的属性和方法
// 私有属性,仅供自身使用的属性和方法,其他外部文件和类无法访问
// 语法:私有属性以下划线开头,如_name,其余均为共有属性
-
类的继承
// 继承是拥有父类的属性和方法
// dart属于单继承,一个类智能拥有一个直接父类,之类拥有父类所有的属性和方法
// 语法:class 类名 extends 父类
// 重写:子类可通过@override注解重写父类方法,扩展其行为
// 注意:子类不会继承父类构造函数,之类必须通过super关键字调用父类构造函数,确保父类正确初始化
// super语法:子类构造函数(可选命名参数):super({参数})
void main(List<String> args) { Child c = Child(name: "老舅", age: 56); } class Parent { String? name = ""; int? age = 0; Parent({this.name, this.age}); void study() { print("父类-$name在学习"); } } class Child extends Parent { Child({String? name, int? age}):super(name: name, age: age); // 传递参数 @override void study() { super.study();// 调用父类的study() print("子类-$name在学习"); } } -
类的多态
// Dart中的类多态是指同一操作作用域不同对象,可以产生不同的执行效果
// 比如微信和支付宝都遵循同样的支付接口,但实现逻辑不同,即同一个支付操作拥有不同的支付结果
// 实现方式:1、继承和方法重写,2.抽象类和接口
// 继承和方法重写
// 继承和方法重写 void main(List<String> args){ PayBase wx = WxPay(); wx.pay(); PayBase ali = AliPay(); ali.pay(); } class PayBase { void pay() { print(“基础支付”); } } // 微信支付 class WxPay extends PayBase { @override void pay() { //super.pay(); print("微信支付"); } } // 阿里支付 class AliPay extends PayBase { @override void pay() { //super.pay(); print("阿里支付"); } }// 抽象类和接口
// 1、使用abstract关键字声明一个抽象类(没有实行体)
// 2、使用implements关键字继承并实现抽象类
void main(List<String> args){ PayBase wx = WxPay(); wx.pay(); PayBase ali = AliPay(); ali.pay(); } abstract class PayBase { void pay(); // 抽象类是不写具体实现的 } // 微信支付 class WxPay implements PayBase { @override void pay() { //super.pay(); print("微信支付"); } } // 阿里支付 class AliPay implements PayBase { @override void pay() { //super.pay(); print("阿里支付"); } } -
类的混入
// 在不使用传统继承的情况下,在类中添加新的功能
// 1、使用mixin关键字定义一个对象
// 2、使用with关键字将定义的对象混入当前对象
// 一个类支持with多个mixin,且遵循后来居上原则,即后混入的会覆盖先混入的同名方法
void main(List<String> args){ Student s = Student(name:"小强"); s.song(s.name); } // 定义一个混入对象 mixin Base { void song(String name) { print("$name在唱歌"); } } class Student with Base { String? name; int? age; Student({this.name.this.age}); } class Teacher with Base { String? name; int? age; Teacher({this.name.this.age}); } -
类的泛型
// 使用类型参数,限定类型的同时又让类型更加灵活。
// 泛型集合、泛型方法、泛型类
void main(List<String> args) { //列表泛型 List<String> list = []; list.add(""); //集合泛型 Map<String,int> map = {}; map["a"] = 2; getValue<String>("1"); printlist<String>(["1","2","3"]); Student<String> s = Student(); s.name = "1"; } //函数泛型 T getValue<T>(T value) { return value } void printlist<T>(List<T> list) { for (var i; i<list.length; i++) { print(list[i]); } } //类的泛型 class Student<T> { T? name; } -
异步编程
-
事件循环
// dart是单线程语言,遇到耗时任务会造成程序阻塞,需要进行异步编程
// dart采用单线程+事件循环的机制完成耗时任务
// 执行同步代码->执行微任务队列->执行事件队列->结束
// 微任务队列:Future.microtask()
// 事件队列:Future、Future.delayed()、I/O操作等
-
Futrue
// Future代表一个异步操作的最终结果
// 状态:Uncompleted(等待)、Completed with a value(成功)、Completed with a error(失败)
// 创建:Future((){})
// 执行成功,不抛出异常-成功状态 then((){})
// 执行失败,throw Exception()-失败状态 catchError((){})
void main(List<String> args) { Futrue f = Futrue((){ //return "hello"; // 没有抛出异常 throw Exception(); }); // then接收成功状态 f.then((value){ print(value); }); f.catchError((error){ print("失败"); }); } -
Future链式调用
// Future可以通过链式的方式连续得到异步的结果
// 通过Futrue().then()得到成功的结果
// 通过Futrue().catchError()得到失败的结果
// 在上一个then返回对象会在下一个then中接收
void main(List<String> args) { Futrue f = Futrue((){ return "hello"; }); f.then((value){ return Future(() => "task1") }).then((value){ return Future(() => "$value-task2"); }).then((value){ return Future(() => "$value-task3"); }).then((value){ throw Exception("异常"); }).catchError((error){ print("失败"); }); } -
Future-async/await
// 除了then/catchError外,还可以通过async/await来实现异步编程
// await总是等到后面的Future执行成功才执行下方逻辑,async必须配套await出现
// 语法:
函数名() async { try { await Future(); //Future执行成功才执行的逻辑 } catch(error) { // 执行失败逻辑 } }void main(List<String> args) { test(); } void test() async { await Future((){ print "测试"; }); //等待延迟3秒 await Future.delayed(Duration(seconds: 3)); // 下方的逻辑都在Futrue执行成功后执行 print("函数执行"); }void main(List<String> args) { test(); } void test() async { try { await Future((){ throw Exception(); }); }catch(e) { print("抛出异常") } }
-