flutter学习笔记 - Dart基本语法(一)

Dart 语言注意事项

  • 文件后缀 .dart
  • 入口方法为 main 方法
  • dart 文件中绝大部分语句都需要分号,像 '{}' 后通常不需要

声明类型

1. 变量声明:var

  • 使用 var 声明的变量,其类型在第一次赋值之后确定,不能再赋其他类型的值

2. 常量声明:

  • const:编译时确定
  • final:运行时确定
  • 表达式里不允许有变量值;一旦确定,不可修改

3. 字符串型:String

4. 数字类型:

  • int:整形
  • num:可整型可小数
  • double:小数

5. 布尔类型:bool

6. 列表类型:List

  • 与数组用法一样,但注意名称

  • 常用方法1:

    • add(内容) 尾部添加
    • addAll(列表) 尾部添加一个列表
    • remove(内容) 删除满足内容的第一个
    • removeLast()删除最后一个
    • removeRange(start, end) 删除索引范围内的数据-左闭右开
  • 常用方法2:

    • 循环 foeEach((item){})
    • 是否都满足条件 every,有返回值(布尔值)
    • 筛选出满足条件的数据 where,有返回值(布尔值),最终会得到一个类似列表的数据,用toList()方法转换
    • 列表的长度 length
    • 最后一个元素 last
    • 第一个元素 first
    • 是否为空 isEmpty

7. 字典类型:Map

  • 场景:存储的英文需要找到对应的中文描述

  • 常用方法:

    • 循环 forEach((key, value){})
    • 尾添一个字典 addAll
    • 是否包含某个key containsKey
    • 删除某个key remove
    • 清空 clear

8. 动态类型:dynamic

  • 允许变量运行时自由改变类型,同时绕过编译时的静态检查

  • 模版字符串:变量名、{变量名或表达式} 在单引号内即可

  • 获取当前时间:DateTime.now()

空安全机制

  1. 定义:在Dart语言中,通过编译静态检查将运行时空指针提前暴露
操作符 符号 作用 示例
可空类型 ? 声明可空变量 String?(允许 String 或 null)
安全访问 ?. 对象为 null 时跳过操作,返回 null user?.name(若 user 为 null 则返回 null)
非空断言 !. 开发者保证变量非空(否则运行时崩溃) name!.length(断言 name 非空)
空合并 ?? 左侧为 null 时返回右侧默认值 name??"Guest(name 为 null 时返回 "Guest")
//shuchuhello 复制代码
void main(List<String> args) {
  String? username = null;
  // 计算机帮我们判断是否为空
  username?.startsWith('前');
  // 开发者主观判断一定不为空(这段代码中运行时是会正常报错的,运行前没报错而已)
  username!.startsWith('前');
  // 因为前面已经主观判定username不为空,所以name一定不是"前天"
  String name = username ?? '前天';
  print(name);
}

函数

1. 函数参数

  • 可选参数:位于必传参数后面,用中括号包裹
    • 语法:函数名(String a, [String?b, ...]),传递时按顺序传递
    • 适用于参数少且顺序固定
javascript 复制代码
String combine(String a, [String? b, String? c]){
    return a + (b ?? "一") + (c ?? "天");
}
  • 可选命名参数:位于必传参数后面,用大括号包裹
    • 语法:函数名(String a, {String?b, ...}),传递时按 参数名:值 的方式传递,顺序不重要
    • 适用于参数多且需明确含义
javascript 复制代码
void main(List<String> args) {
  person("老王", sex: "男", age: 20);
}
// 若不传age、性别,会为null,设置默认值好点
void person(String username, {int? age = 18, String? sex = "男"}) {
  print('姓名:${username},年龄:${age},性别:${sex}');
}

2. 匿名函数

  • 可以声明一个没有名称的函数赋值给变量,进行调用
  • 语法:Function 变量名 = (){}
javascript 复制代码
void main(List<String> args) {
  Function add = () {
    print('这是匿名函数');
  };
  add();
}

3. 箭头函数

  • 语法:函数名()=>代码逻辑
scss 复制代码
void main(List<String> args) {
  print(test('这是箭头函数'));
  print1();
}

String test(String a) => a;
void print1() => print('Hello');

类-class

  • 定义类语法:class 类名 { 属性 方法 }
  • 实例化对象:类名 变量名 = 类名();
  • 属性和方法:变量.属性/方法();
ini 复制代码
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在学习');
  }
}

类-构造函数

实例化对象的时候,使用构造函数直接给对象中的属性赋值

1. 默认构造函数:

  • 定义语法:
arduino 复制代码
class 类名 {
    类名(可选命名参数){
    }
}
  • 实例化语法:Person p = new Person(属性: 值)
ini 复制代码
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在学习');
  }
}

2. 命名构造函数

  • 定义语法:
arduino 复制代码
class 类名 {
    类名.构造函数名(可选命名参数){
    }
}
  • 实例化语法:Person p = new Person.构造函数名(属性: 值)
ini 复制代码
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在学习');
  }
}

3. 构造函数语法糖

  • 简写语法:
kotlin 复制代码
class 类名 {
    类名({this.属性1, this.属性2});
    
    类名.构造函数名({this.属性1, this.属性2});
}

类-公有属性和私有属性

以下划线开头为私有属性,如_name,其余均为公有属性

类-继承

继承是拥有父类的属性和方法,dart属于单继承,一个类只能拥有一个直接父类,子类拥有父类所有的属性和方法

  • 语法:class 类名 extends 父类
  • 重写:子类可通过@override注解重写父类方法,扩展其行为
  • 注意:子类不会继承父类构造函数,子类必须通过super关键字调用父类构造函数确保父类正确初始化
  • super语法:子类构造函数(可选命名参数): super({参数})
dart 复制代码
void main(List<String> args) {
  Child p = Child(name: "老王", age: 20);
  p.study();
}

class Person {
  String? name = "";
  int? age = 0;
  // 命名构造函数
  Person({this.name, this.age});
  void study() {
    print('$name在学习');
  }
}

class Child extends Person {
  Child({String? name, int? age}) : super(name: name, age: age);
  @override
  void study() {
    // TODO: implement ==
    // super.study();调用父类方法
    print('子类-$name在学习');
  }
}

类的多态

  • 继承和方法重写
  • 抽象类和接口
    • 使用abstract关键字声明一个抽象类(没有实现体),使用implements关键字继承并实现抽象类
typescript 复制代码
void main(List<String> args) {
  PayBase wx = WxPay();
  PayBase ali = AliPay();
  wx.pay();
  ali.pay();
}

abstract class PayBase {
  void pay(); // 抽象类不写具体实现
}

class WxPay implements PayBase {
  @override
  void pay() {
    print("微信支付");
  }
}

class AliPay implements PayBase {
  @override
  void pay() {
    print("支付宝支付");
  }
}

类的混入

Dart允许在不使用传统继承的情况下,向类中添加新的功能

  • 方法:使用mixin关键字定义一个对象,使用with关键字将定义的对象混入到当前对象
scala 复制代码
void main(List<String> args) {
  Student s = Student(name: '小华');
  s.song(s.name!); // 设置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});
}
  • 注意:一个类支持with多个mixin,调用优先级遵循"后来居上"原则

泛型

  1. 定义:Dart允许使用类型参数,限定类型的同时又让类型更加灵活,让代码更加健壮和维护性更强
  • 列表泛型:List<类型> 变量名 = []
  • 字典泛型:Map<String, int> map = {}; 里面分别是键、值类型
  • 函数泛型
csharp 复制代码
void main(List<String> args) {
  print(getValue<String>("1"));
  print(getList<String>(["1", '2']));
}

T getValue<T>(T value) {
  return value;
}

T getList<T>(List<T> value) {
  return value[0];
}
  • 类里的泛型
ini 复制代码
void main(List<String> args) {
  Student<int> s = Student();
  s.name = 1;
}

class Student<T> {
  T? name;
}

Dart中的异步编程

Dart是单线程语言,同时只能做一件事,遇到耗时任务就会造成程序阻塞,此时需要异步编程

  • 微任务队列:Future.microtask()
  • 事件队列:Future、Future.delayed()、I/O操作等

1. Future

  • Future代表一个异步操作的最终结果
  • 状态:Uncompleted等待、Completed with a value成功、Completed with a error失败
  • 创建语法:Future((){})
    • 执行成功:不抛出异常-成功状态、catchError((){})
    • 执行失败:throw Exception()-失败状态-catchError((){})
javascript 复制代码
void main(List<String> args) {
  // 定义一个Future对象
  Future f = Future(() {
    return "hello";
    // 没有抛出错误 就是成功状态
    // throw Exception();
  });
  f.then((value) {
    print(value);
  });
  // f.catchError((err) {
  //   print("出错了");
  // });
}
  • 链式调用
javascript 复制代码
void main(List<String> args) {
  Future(
    () => "hello",
  )
  .then((value) => throw Exception())
  .catchError((err) => print("出错wu了"));
}

2. async/await

  • await总是等到后面的Future执行成功,才执行下方逻辑,async必须配套await出现
  • 语法:
scss 复制代码
函数名()async{
    try{
    await Future();
    // Future执行成功才执行的逻辑
    }
    catch(error){
    // 执行失败的逻辑
    }
   }
  • 补充:
  • Future.delayed(Duration(seconds:3))delayed延时函数,Duration时间对象,所以这里是延时3秒
相关推荐
用户游民8 小时前
Flutter Provider原理以及用法
前端·flutter
qq_140303414410 小时前
flutter
flutter
程序员老刘1 天前
为什么AI不会淘汰Flutter,反而让它更吃香了
flutter·ai编程·客户端
蝎子莱莱爱打怪1 天前
我花两年业余时间做了个IM系统,然后呢😂??
后端·flutter·面试
Swuagg1 天前
Flutter EventBus 架构设计:基于 Stream 的事件总线实现与实践
flutter·eventbus·事件总线
恋猫de小郭1 天前
Jetbrains 官宣正式发布 KMP 全新默认项目结构,向着 Amper 靠近
android·前端·flutter
光影少年1 天前
大前端框架生态
前端·javascript·flutter·react.js·前端框架·鸿蒙·angular.js
BG2 天前
Flutter PSD 解析实践:利用ag-psd 解析 + 分块图片编码,同时解决移动端OOM
flutter