Skip to content

dart 学习

名称连接备注
Flutter中文官网https://flutterchina.club
Flutter中文官方安装教程https://flutterchina.club/get-started/install/
dart官方语言https://dart.cn/
flutter官方文档https://docs.flutter.dev/get-started/install
flutter官方的中文文档https://docs.flutter.cn/release/archive

1.简介

1.1 简介

Flutter 是 Google 推出并开源的移动应用开发框架,主打跨平台、高保真、高性能。开发者可以通过 Dart 语言开发 App,一套代码同时运行在 iOS 和 Android平台。 Flutter 提供了丰富的组件、接口,开发者可以很快地为 Flutter 添加 Native(即原生开发,指基于平台原生语言来开发应用,flutter可以和平台原生语言混合开发) 扩展。下面我们整体介绍一下 Flutter 技术的主要特点。

1.2 安装flutter

由于Flutter会同时构建Android和IOS两个平台的发布包,所以Flutter同时依赖Android SDK和iOS SDK,在安装Flutter时也需要安装相应平台的构建工具和SDK。都是以下三步

  1. flutter sdk
  2. Android sdk
  3. Xcode sdk

1.2.1 mac安装

Flutter sdk安装

目前新版版的flutter是包含 dart 环境的,无需额外安装

点击:https://docs.flutter.cn/release/archive

选择自己的版本并且下载

image-20250212101100037

首先解压安装包

image-20250212101314180

然后把下面的安装路径给替换 $PWD就是

bash
cat <<EOT >> ~/.zprofile
export PUB_HOSTED_URL="https://pub.flutter-io.cn"
export FLUTTER_STORAGE_BASE_URL="https://storage.flutter-io.cn"
export PATH="$PWD/flutter/bin:$PATH"
EOT

替换成真正的安装路径

bash
cat <<EOT >> ~/.zprofile
export PUB_HOSTED_URL="https://pub.flutter-io.cn"
export FLUTTER_STORAGE_BASE_URL="https://storage.flutter-io.cn"
export PATH="/Users/luckincoffee/Desktop/app/flutter/bin:$PATH"
EOT

然后让配置环境生效

bash
source ~/.zprofile

运行 Flutter doctor 来验证安装。

flutter doctor

image-20250212112756364

第一个❌ 是因为没安装Android sdk 暂时先忽略 第二个❌是没安装xcode,安装最新的xcode

安装android sdk

https://developer.android.com/studio?hl=zh-cn

在这里插入图片描述

SDK Command-line Tools 安装;其他的配置根据自己情况勾选安装;

在这里插入图片描述

随后在终端执行:

这个提示代表Android 许可证状态未知,让我们运行flutter doctor --android-licenses来解决。

按照提示执行

typescript
flutter doctor --android-licenses

最后执行flutter doctor -> 查看Adnroid 配置是否完成;

image-20250212142041789

安装mac sdk-xcode

https://developer.apple.com/download/all

image-20250212141522870

不知道选择什么版本的,看这个页面数据:https://developer.apple.com/cn/support/xcode/

数据比较大

image-20250212142110139

安装完成后在终端执行:flutter doctor ->查看xcode是否配置成功

下载完毕后,一定要移动到这里,然后再开始安装

image-20250212150459148

选择平台,点击安装,速度非常慢

image-20250212142150320

然后运行代码

bash
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
sudo xcodebuild -runFirstLaunch

flutter doctor 最终效果

在这里插入图片描述

https://developer.apple.com/documentation/xcode-release-notes/xcode-15_3-release-notes

Mac

brew install --cask flutter

参考资料

https://blog.csdn.net/weixin_46418118/article/details/140719665

1.2.2 windows安装

1.3 编译器

Android Studio

安装插件

  • Flutter插件: 支持Flutter开发工作流 (运行、调试、热重载等)。
  • Dart插件: 提供代码分析 (输入代码时进行验证、代码补全等)。

image-20250212152703305

image-20250212154305790

vscode

安装插件

image-20250212152119270

体验热重载

  1. 打开lib/main.dart文件。
  2. 将字符串 'You have pushed the button this many times:' 更改为 'You have clicked the button this many times:'
  3. 不要按“停止”按钮; 让您的应用继续运行。
  4. 要查看您的更改,直接保存(cmd+s / ctrl+s),或者点击 热重载按钮 (绿色圆形箭头按钮)即可。

你会立即在运行的应用程序中看到更新的字符串。

2. dart语言

在线dart编译器,基本上打不开:https://dartpad.dev/image-20250212144357712

我们创建完成项目后,学习一下dart语言

image-20250212195239276

执行命令即可运行

bash
dart test.dart

image-20250212210320789

2.1 入门

参考资料

https://blog.csdn.net/weixin_62700590/article/details/139327817

1) 入口函数main

dart
void main(){
 print("hello world");
}

2) 注释

单行注释

dart
// Symbol libraryName = new Symbol('dart.core');

多行注释

dart
/*

* Symbol

*

Symbol libraryName = new Symbol('dart.core'); MirrorSystem mirrorSystem = currentMirrorSystem(); LibraryMirror libMirror = mirrorSystem.findLibrary(libraryName); libMirror.declarations.forEach((s, d) => print('$s - $d'));

*/

文档注释

/// main 函数 /// /// 符号 /// 枚举 /// void main() { ... }

类、函数 请用 /// 方式定义,后期导出文档有帮助

3) 函数

定义,调用

dart

int add(int x) {
  return x + 1;
}


void main(){
 //  打印
 print(add(1));
}

可选参数

dart

int add(int x, [int y = 1, int z = 2]) {
  return x + y;
}



void main(){
 //  打印
 print(add(1));
}
  • 可选参数:

    使用方括号 [] 来定义可选参数 y 和 z。调用函数时可以选择传入或者不传入这两个参数。

  • 可空类型:

    int? 表示 int 类型的值可以是 null。如果没有使用 int?,那么 Dart 不允许把 null 赋值给该参数。

  • 默认值逻辑:

    在函数内部,通过 if (y == null) 和 if (z == null) 检查 y 和 z 是否为 null,如果是则赋值为默认的 1。

命名参数 默认值

dart

int add({int x = 1, int y = 1, int z = 1}) {
  return x + y + z;
}


void main(){
 //  打印
 print(add(x:1,y:3,z: 4));
}

这个会比可选参数更灵活,可以调用的时候再指定传参

函数内定义

dart
void main(){
  int add(int x){
    return x + x;
  }
  print(add(1));
}

Funcation 返回函数对象

dart

Function makeAdd(int x) {
  return (int y) => x + y;
}

void main(){
 //  打印
  var add = makeAdd(1);
  print(add(5));
}

匿名函数

dart


void main(){
 //  打印
  const list = ['apples', 'bananas', 'oranges'];
  list.forEach((item) {
    print('${list.indexOf(item)}: $item');
  });
}

image-20250212211557544

作用域

dart
bool topLevel = true;
 
void main() {
  var insideMain = true;
 
  void myFunction() {
    var insideFunction = true;
 
    void nestedFunction() {
      var insideNestedFunction = true;
 
      assert(topLevel);
      assert(insideMain);
      assert(insideFunction);
      assert(insideNestedFunction);
    }
  }
}

注意 nestedFunction() 函数可以访问包括顶层变量在内的所有的变量。简单说就是被包含的作用域内可以访问包含其的外部变量

4) 数据类型

在 Dart 中,基本类型包括以下几种:intdoublenumboolStringListSetMapRuneSymbolNull。这些类型构成了 Dart 中最核心的部分,开发者可以使用这些类型来处理几乎所有常见的任务。以下是对每种类型的详细说明。

数值类型(intdoublenum)

  • int:表示整数,值没有小数部分,适用于处理不带小数的数值。
  • double:表示浮点数,适用于包含小数部分的数值。
  • num:是 intdouble 的父类,它可以存储任何数值(整数和浮点数)。
类型描述示例
int整数类型int a = 10;
double浮点数类型double b = 3.14;
num数值类型(包含整数和浮点数)num c = 10;num d = 3.14;

示例:

dart
void main() {
  int age = 30;
  double height = 1.75;
  num weight = 68.5;

  print("Age: $age");       // 输出:Age: 30
  print("Height: $height"); // 输出:Height: 1.75
  print("Weight: $weight"); // 输出:Weight: 68.5
}

布尔类型 (bool)

bool 表示布尔类型,有两个可能的值:truefalse。布尔类型常用于条件判断和逻辑运算。

类型描述示例
bool布尔类型bool isActive = true;

示例

dart
void main() {
  bool isLoggedIn = true;
  bool hasAccess = false;

  if (isLoggedIn) {
    print('User is logged in.'); // 输出:User is logged in.
  }
  
  if (!hasAccess) {
    print('Access denied.');     // 输出:Access denied.
  }
}

字符串类型 (String)

String 用于表示文本。它是不可变的,也就是一旦创建,字符串内容不能修改。可以使用单引号或双引号来定义字符串。

类型描述示例
String字符串String name = 'Dart';

示例

dart
void main() {
  String greeting = 'Hello';
  String name = "Dart";

  String message = '$greeting, $name!'; // 使用插值
  print(message);  // 输出:Hello, Dart!
}

列表类型 (List)

Dart 提供了三种主要的集合类型:List(列表)、Set(集合)和 Map(映射)。

List 是一个有序的集合,可以包含重复的元素。可以通过索引来访问和修改列表中的元素。

类型描述示例
List列表类型List<int> numbers = [1, 2, 3];
dart
void main() {
  List<String> fruits = ['Apple', 'Banana', 'Orange'];
  print(fruits[0]);  // 输出:Apple
  
  fruits.add('Mango');
  print(fruits);     // 输出:[Apple, Banana, Orange, Mango]
}

集合类型 (Set)

Set 是一个无序且元素唯一的集合。它不会包含重复的元素

类型描述示例
Set集合类型Set<int> uniqueNumbers = {1, 2, 3};

示例

dart
void main() {
  Set<int> numbers = {1, 2, 3, 3};
  print(numbers); // 输出:{1, 2, 3}
  
  numbers.add(4);
  print(numbers); // 输出:{1, 2, 3, 4}
}

映射类型 (Map)

Map 是键值对的集合,用于存储关联数据。每个键只能对应一个值。

类型描述示例
Map映射类型Map<String, int> ages = {'Alice': 30, 'Bob': 25};
dart
void main() {
  Map<String, int> ages = {'Alice': 30, 'Bob': 25};
  print(ages['Alice']);  // 输出:30
  
  ages['Charlie'] = 20;
  print(ages);           // 输出:{Alice: 30, Bob: 25, Charlie: 20}
}

符号类型 (Symbol)

Symbol 类型表示 Dart 程序中的操作符或标识符。符号类型在反射和代码生成时非常有用。

类型描述示例
Symbol符号类型Symbol symbol = #foo;

示例

dart
void main() {
  Symbol symbol = #foo;
  print(symbol);  // 输出:Symbol("foo")
}

Runes

Runes 用于表示 Unicode 字符。Dart 的 String 是 UTF-16 编码的字符串,但有些 Unicode 字符超出这个范围,这时需要使用 Runes 来处理。

类型描述示例
RunesUnicode 字符Runes input = Runes('😀');

示例

dart
void main() {
  Runes heart = Runes('\u2665');  // 使用 Unicode
  print(String.fromCharCodes(heart)); // 输出:♥
}

空类型 (Null)

Null 类型表示没有值。在 Dart 2.12 之后,启用了空安全(null safety),使得变量默认不可为空。这意味着在 Dart 中,除非明确声明,否则变量不能存储 null 值。

示例

dart
void main() {
  int? age = null; // 使用 `?` 允许变量为空
  print(age);  // 输出:null
  
  age = 30;
  print(age);  // 输出:30
}

5) 变量

在Dart 中,变量用于存储数据。Dart 是一种强类型语言,这意味着每个变量都有一个明确的类型。尽管 Dart 有类型推断的功能,但理解并正确使用变量的声明和类型是非常重要的。

变量的声明

Dart 中声明变量的常用关键字有 varfinalconst

va r

类似于 JavaScript 中的var,它可以接收任何类型的变量,但最大的不同是 Dart 中 var 变量一旦赋值,类型便会确定,则不能再改变其类型,如:

dart
var t = "hi world";
// 下面代码在dart中会报错,因为变量t的类型已经确定为String,
// 类型一旦确定后则不能再更改其类型。
t = 1000;

上面的代码在 JavaScript 是没有问题的,前端开发者需要注意一下,之所以有此差异是因为 Dart 本身是一个强类型语言,任何变量都是有确定类型的,在 Dart 中,当用var声明一个变量后,Dart 在编译时会根据第一次赋值数据的类型来推断其类型,编译结束后其类型就已经被确定,而 JavaScript 是纯粹的弱类型脚本语言,var 只是变量的声明方式而已。

使用 final 声明的变量只能赋值一次,之后不能再修改该变量的值。

Dart
final city = '北京'; // city 的值不能再被更改

const 关键字声明的变量在编译时就已确定为常量,不能被修改。const 常量与 final 的区别是:const 是编译时常量,final 是运行时常量。

Dart
const pi = 3.14159; // pi 的值在编译时就被确定了

dynamicObject

Object 是 Dart 所有对象的根基类,也就是说在 Dart 中所有类型都是Object的子类(包括Function和Null),所以任何类型的数据都可以赋值给Object声明的对象。 dynamicObject声明的变量都可以赋值任意对象,且后期可以改变赋值的类型,这和 var 是不同的,如:

dart
dynamic t;
Object x;
t = "hi world";
x = 'Hello Object';
//下面代码没有问题
t = 1000;
x = 1000;

dynamicObject不同的是dynamic声明的对象编译器会提供所有可能的组合,而Object声明的对象只能使用 Object 的属性与方法, 否则编译器会报错,如:

dart
 dynamic a;
 Object b = "";
 main() {
   a = "";
   printLengths();
 }   

 printLengths() {
   // 正常
   print(a.length);
   // 报错 The getter 'length' is not defined for the class 'Object'
   print(b.length);
 }

dynamic 的这个特点使得我们在使用它时需要格外注意,这很容易引入一个运行时错误,比如下面代码在编译时不会报错,而在运行时会报错:

dart
print(a.xx); // a是字符串,没有"xx"属性,编译时不会报错,运行时会报错

2.2 操作符

算术操作符

操作符描述示例结果
+加法5 + 38
-减法5 - 32
*乘法5 * 315
/除法5 / 22.5
~/整数除法5 ~/ 22
%取余数5 % 21
-expr一元负号-a取反 a 的值

赋值操作符

赋值操作符用于将值赋给变量,并支持与算术操作符结合的复合赋值操作。

操作符描述示例结果
=赋值a = bb 赋给 a
+=加法赋值a += ba = a + b
-=减法赋值a -= ba = a - b
*=乘法赋值a *= ba = a * b
/=除法赋值a /= ba = a / b
~/=整数除法赋值a ~/= ba = a ~/ b
%=取余赋值a %= ba = a % b
??=空值赋值a ??= b如果 anull,则赋值 b

示例

dart
void main() {
  int a = 5;
  a += 3;   // 相当于 a = a + 3
  print(a); // 输出: 8
 
  double b = 10.0;
  b /= 2;   // 相当于 b = b / 2
  print(b); // 输出: 5.0
 
  String? name;
  name ??= 'Dart'; // 如果 name 为 null,则赋值 'Dart'
  print(name); // 输出: Dart
}

比较操作符

比较操作符用于比较两个值,结果为布尔值 truefalse

操作符描述示例结果
==等于a == b如果 a 等于 b,则为 true
!=不等于a != b如果 a 不等于 b,则为 true
>大于a > b如果 a 大于 b,则为 true
<小于a < b如果 a 小于 b,则为 true
>=大于等于a >= b如果 a 大于等于 b,则为 true
<=小于等于a <= b如果 a 小于等于 b,则为 true

示例

dart
void main() {
  int a = 5;
  int b = 3;
 
  print(a == b);  // 输出: false
  print(a != b);  // 输出: true
  print(a > b);   // 输出: true
  print(a < b);   // 输出: false
  print(a >= b);  // 输出: true
  print(a <= b);  // 输出: false
}

逻辑操作符

操作符描述示例结果
&&逻辑与a && bab 都为 true,结果为 true
| |`
!逻辑非!aatrue,结果为 false
dart
void main() {
  bool a = true;
  bool b = false;
 
  print(a && b);  // 输出: false
  print(a || b);  // 输出: true
  print(!a);      // 输出: false
}

位操作符

操作符描述示例结果
&按位与a & bab 的每一位执行与操作
``按位或`a
^按位异或a ^ bab 的每一位执行异或操作
~expr按位取反~aa 的每一位取反
<<左移a << ba 的二进制位左移 b
>>右移a >> ba 的二进制位右移 b
>>>无符号右移a >>> b无符号右移 b 位(Dart 2.14 引入)
dart
void main() {
  int a = 5;  // 二进制:0101
  int b = 3;  // 二进制:0011
 
  print(a & b);   // 输出: 1  (0001)
  print(a | b);   // 输出: 7  (0111)
  print(a ^ b);   // 输出: 6  (0110)
  print(~a);      // 输出: -6 (取反)
  print(a << 1);  // 输出: 10 (1010)
  print(a >> 1);  // 输出: 2  (0010)
}

类型测试操作符

操作符描述示例结果
is检查对象是否为指定类型a is int如果 aint 类型,结果为 true
is!检查对象是否不是指定类型a is! String如果 a 不是 String 类型,结果为 true
as类型转换a as Stringa 转换为 String 类型(如果类型不匹配会抛出异常)

示例

dart
void main() {
  dynamic a = 'Hello';
 
  if (a is String) {
    print('a 是字符串');
  }
 
  String b = a as String;
  print(b); // 输出: Hello
}

条件表达式

三元运算符

条件表达式用于根据条件的真假来选择性地执行代码。

语法:condition ? expr1 : expr2

conditiontrue 时,结果为 expr1;否则结果为 expr2

dart
void main() {
  int a = 5;
  String result = (a > 3) ? '大于3' : '小于等于3';
  print(result); // 输出: 大于3
}

空值合并运算符

操作符描述示例结果
??如果左侧值为 null,返回右侧值a ?? b如果 anull,结果为 b
??=如果变量为 null,赋值右侧值a ??= b如果 anull,则 a = b

示例:

json
void main() {
  String? name;
  String greeting = 'Hello, ' + (name ?? 'Guest');
  print(greeting); // 输出: Hello, Guest
 
  name ??= 'Dart';
  print(name); // 输出: Dart
}

级联操作符

级联操作符用于对同一个对象连续执行多个操作。

操作符描述示例
..级联操作符object..method1()..method2()
?..空安全级联操作符object?..method()

示例:

dart
class Builder {
  int? width;
  int? height;
  String? color;

  void setWidth(int w) => width = w;
  void setHeight(int h) => height = h;
  void setColor(String c) => color = c;
}

void main() {
  Builder builder = Builder()
    ..setWidth(100)
    ..setHeight(200)
    ..setColor('red');

  print('宽度: ${builder.width}, 高度: ${builder.height}, 颜色: ${builder.color}');
  // 输出: 宽度: 100, 高度: 200, 颜色: red
}

访问操作符

用于访问对象的属性或方法,或调用函数。

操作符描述示例
.访问成员object.property
?.空安全访问成员object?.property
[]访问集合的元素list[index]
?[]空安全访问集合的元素list?[index]
()调用函数或方法function()

示例

dart
void main() {
  List<int>? numbers;

  print(numbers?[0]); // 输出: null,不会抛出异常

  numbers = [1, 2, 3];
  print(numbers[0]);  // 输出: 1
}

扩展操作符

用于在集合中插入另一个集合的所有元素。

操作符描述示例
...扩展运算符[...list]
...?空安全扩展运算符[...?list]
dart
void main() {
  List<int> list1 = [1, 2, 3];
  List<int>? list2;

  List<int> combinedList = [0, ...list1, ...?list2];
  print(combinedList); // 输出: [0, 1, 2, 3]
}

异步操作符

awaitasync

用于处理异步操作。

dart
Future<String> fetchData() async {
  await Future.delayed(Duration(seconds: 2));
  return '数据加载完成';
}
 
void main() async {
  print('开始加载');
  String data = await fetchData();
  print(data); // 输出: 数据加载完成(延迟2秒)
}
yieldyield*

用于生成器函数。

dart
Stream<int> countStream(int max) async* {
  for (int i = 1; i <= max; i++) {
    yield i;
  }
}

void main() async {
  await for (int i in countStream(3)) {
    print(i); // 输出: 1 2 3
  }
}

操作符重载

Dart 允许在类中重载部分操作符,使其适用于自定义对象。

可重载的操作符包括:

  • 算术操作符:+-*/~/%
  • 比较操作符:==><>=<=
  • 位操作符:&|^~<<>>
  • 索引操作符:[][]=
  • 一元操作符:-~

参考资料:https://blog.csdn.net/ljguo2008/article/details/142320378

2.4 流程控制

if else;for;while;do while;switch case;break;continue;相信这些就不用博主多说了哈

值得一提的是 continue 有一点不一样

continue 跳转指定位置(就像cpp的go to,新增了这个功能)

dart
String command = "close";
switch (command) {
  case "open":
    print("open");
    break;
  case "close":
    print("close");
    continue doClear;
  case "close2":
    print("close2");
    continue doClear;
 
  doClear:
  case "doClose":
    print("doClose");
    break;
 
  default:
    print("other");
}

2.5 异常

使用 try-catch 捕获异常

try-catch 语句用于捕获并处理抛出的异常。try 块中的代码如果抛出异常,程序将跳转到 catch 块进行处理。

dart
try {
  // 可能会抛出异常的代码
} catch (e) {
  // 捕获并处理异常
}

异常处理的 finally

finally 块用于定义无论是否抛出异常都要执行的代码。它通常用于关闭资源或释放占用的资源,例如文件或网络连接。

dart
try {
  // 可能抛出异常的代码
} catch (e) {
  // 捕获异常
} finally {
  // 始终执行的代码
}

使用 on 捕获特定异常

如果知道某个代码段可能抛出的具体异常类型,使用 on 来捕获特定异常比使用 catch 更加高效且明确

dart
void main(){
  try {
    throw new OutOfMemoryError();
  } on OutOfMemoryError {
    print('没有内存了');
    rethrow;
  } catch (e) {
    print("捕获异常");
    print(e);
  } finally {
    print('end');
  }
}

2.6 类

dart
class Animal {
  String name;
  int age;
  String color;

  Animal(this.name, this.age, this.color);

  void eat() {
    print("$name is eating");
  }

  void run() {
    print("$name is running");
  }
}

主函数

dart
import 'lib/Animal.dart';

void main() {
  Animal animal = new Animal("Dog", 2, "Black");
  animal.eat();
  animal.run();
}

image-20250213203632122

导入系统的库

dart
import 'dart:math';

void main() {
  var random = Random();
  print(sqrt(16));
  print(max(10, 20));
  print(min(10, 20));
  print(random.nextInt(10));
  print(random.nextDouble());
  print(random.nextBool());
}

注解

在 Dart 中,注解(Annotations)是一种元数据,可以为代码中的类、字段、方法、参数等添加附加信息。注解通常用于标记代码中的特定元素,以影响编译、运行时行为,或供框架和工具进行处理。注解以@符号开头,紧跟着一个标识符,或者是一个调用构造函数的表达式。

Dart 中的注解与 Java 等其他语言的注解类似。它们可以用于代码生成、编译时检查、反射等场景,常用于构建器、测试框架等。

Dart 提供了一些内置的注解,常见的有以下几种:

  • @override:用于标明一个方法重写了父类中的方法。
  • @deprecated:标记某个元素为过时的,会在使用时触发编译器警告。
  • @required:用于标记一个命名参数是必需的(Dart 2.12 以前使用,现已被 required 修饰符代替)。
  • @pragma:影响编译器的行为,通常不直接使用。

参考教程 https://blog.csdn.net/ljguo2008/article/details/142320378

https://xtermjs.org/

3. flutter入门