前言

本篇是本人学习dart 的学习笔记,由于本人有其他语言的基础,所以有些地方不会写的很细。
这里是看这个教程,还是比较推荐的。
黑马程序员Flutter从入门到实战全套视频教程,从Dart语言到Flutter核心框架AI辅助开发,一套搞定Android、iOS、HarmonyOS及Web

flutter 安装

https://docs.flutter.cn/community/china/

1、下载flutter

flutter 安装还非常简单的,你只需要下载下来,然后解压缩,再配置一下环境变量就行了。

这里也提供对应的链接
https://storage.flutter-io.cn/flutter_infra_release/releases/stable/windows/flutter_windows_3.35.5-stable.zip

下载之后,进行解压缩即可。

2、配置环境变量

打开 设置

在设置中搜索环境变量,找到编辑环境变量

需要添加两个环境变量

PUB_HOSTED_URL=https://mirrors.tuna.tsinghua.edu.cn/dart-pub
FLUTTER_STORAGE_BASE_URL=https://mirrors.tuna.tsinghua.edu.cn/flutter

只需要在这里写上变量名就行了。
在这里插入图片描述

为什么我们要在dart教程里面,安装flutter呢?
1.flutter里面自带dart
2.dart现在最常用的就是flutter框架了,顺便安装一下。

变量

dart 的 变量跟其他的区别不是很大,主要记住以下几点

var //声明变量,dart会自己推断类型,很方便,就像在用python,js等
final // 声明运行时常量
const	// 声明编译时常量
类型名	//使用 int等来声明变量

var

使用var 声明变量的时候需要注意,
变量声明之后,变量的类型不能改变。

void main(){
  var a = 1;
  a = a.toString();
  print(a);
}

可以试一下这个,会报错,但是python不会

const

是用const声明变量的时候,需要注意
const 是编译时常量,在编译的时候,就确定的常量
const中不能有变量,不能使用表达式

void main(){
  var a = 1;
  const b = a*2;
  print(b);
}

可以试一下这个

final

final 是运行时常量,比如,文章发表的时间是固定的,并且你也不想让他修改,就可以使用final ,并且final 还可以使用表达式。

void main(){
  var a = 1;
  final b = a*2;
  print(b);
}

可以试一下这个,可以就能正常运行。

变量类型

dart 的变量类型,跟其他语言没有太多的差别

dart 的类型还是分为,值类型,集合类型和特殊用途类型
特殊用途类型可以自己google 一下,比如 symbol,type等,我觉得暂时这里就不说了,一般这种都属于进阶内容,也不常用。

值类型

值类型分为 数值类型,字符串类型和布尔类型
数值类型分为 int类型和double类型,也就是整数类型和浮点数类型,
在dart里面还有一个num类型,既可以声明int,也可以声明double。

下面说一下值类型常用的操作,这在其他语言里面也常用的。

算术运算

int a = 5;
int b = 2;

a + b;   // 7
a - b;   // 3
a * b;   // 10
a / b;   // 2.5   永远是 double
a ~/ b;  // 2    整除(向下取整)
a % b;   // 1

a += 1;
a -= 2;
a *= 3;
a ~/= 2;

a++;
++a;

学会这些代码,就相当于掌握编程里面的运算了
但是我这里要说一下在写代码时候的原则,写代码,永远是怎么简单,少歧义,怎么来。在编写业务代码的时候,永远都是看一眼就知道写的是什么的代码才是好代码。

++a这种写法是语法能运行的,但是尽量不要写
原因是,容易给自己,给其他人挖坑。

运算优先级

我们在上学的时候,都学过,先算乘除,再算加减。这里我不教你复杂的规则,这里我只教你一句话

括号的优先级是最高的,编程语言永远都是先计算括号里面,再一步一步向外面计算。遇到拿不定主意的,请一定要使用括号!!!

类型转换

类型转换就是把int类型转成double 类型,把double类型转成int类型,
后面我们还会学习字符串类型,也能进行相互转换。

int a = 10;

double d = a.toDouble();
int b = d.toInt();       // 截断
int c = d.round();       // 四舍五入
int e = d.floor();       // 向下取整
int f = d.ceil();        // 向上取整

数学函数

在我们开发的时候,经常会需要用到一些数学处理,比如最大值,最小值,指数函数,等等吧。

你可以自己实现,也可以使用标准库。

注意:
不要成为只会调包的人,在调包的时候,多想一想怎么实现的。

比如max怎么实现?
min怎么实现?
如果你是看我的博文看到这里,并且还没有编程基础,这个一个超纲题,需要你要有后面的知识。

import 'dart:math';

void main(){
  int a = 10;
  int b = 20;
  print(max(a, b));
  print(min(a, b));
  print(sqrt(16));
  print(pow(2, 3));   // 8
}

模版字符串

模版字符串,简单来说就是,你想在字符串中间带上一点变量,当这个变量出现不同的值,打印出来的东西也不一样。
语法很简单

'hello $name'
'age=${age + 1}'
'len=${list.length}'

就这两种情况,我比较推荐使用表达式的方式,比较万能,不容易踩坑。

字符串类型转换

int.tryParse('123') ?? 0;
double.tryParse('3.14') ?? 0.0;
123.toString();
3.14159.toStringAsFixed(2); // 3.14

字符串常用操作

我们日后会进行跟字符串打交道,会有各种各样的需要
我这里不一定能写全

查询字符串的基本信息
String s = 'hello world';

s.length;        // 长度
s.isEmpty;       // 是否为空
s.isNotEmpty;    // 是否非空
字符串拼接
var name = 'Tom';
var age = 18;

'hello $name';
'age=${age + 1}';
var buf = StringBuffer();
buf.write('a');
buf.write('b');
var s = buf.toString();

查找
s.contains('world');
s.startsWith('hello');
s.endsWith('ld');

s.indexOf('o');       // 找不到返回 -1
s.lastIndexOf('o');

截取
s.substring(0, 5); // hello
替换
s.replaceAll('o', '0');
s.replaceFirst('o', '0');

分割
'a,b,c'.split(',');   // ['a', 'b', 'c']

合并
['a', 'b', 'c'].join('-'); // a-b-c

大小写&去掉空格
s.toUpperCase();
s.toLowerCase();

'  hi  '.trim();
'  hi'.trimLeft();
'hi  '.trimRight();

正则表达式

正则表达式是一种用于匹配和操作文本的强大工具,它是由一系列字符和特殊字符组成的模式,用于描述要匹配的文本模式。

正则表达式可以在文本中查找、替换、提取和验证特定的模式。

这个,只要会用就行了,能用大模型写正则表达式就行了,正则表达式非常抽象,人肉写的话,学习成本非常高,所以这里我一般都是使用大模型来写。

多行字符串
var s = '''
line1
line2
line3
''';

驼峰命名法和下划线命名法

这个东西非常重要,算是约定俗成的东西

驼峰命名法,分为大驼峰命名法和小驼峰命名法
说人话就是,英文单词的首字母是否大写
大小驼峰命名法的区别是,变量的首字母是否大写

isWorkFinished //小驼峰命名法
IsWorkFinished //大驼峰命名法

下划线命名法又叫蛇形命名法,snake_case,简单来说就是,在字符串之间用下划线进行分割。

metric_processor //下划线命名法

不同语言对于变量,文件名,都有不同的约定,dart大概如下。

变量小驼峰,类名大驼峰
私有加下划线,文件用下划线
bool 要有 is,集合要复数

命名法尽量遵守,这样写出来的代码更好看一点,别人也能看得懂。
这里我写一点反例

// 单字母乱飞
var a = 10;
var b = 'hello';
var c = true;

//使用拼音
var shijian = DateTime.now();
var yonghuId = 123;
// 滥用缩写
var cfg = loadCfg();
var usrMgr = UserMgr();

变量命名总的来说,就是要清晰明了,让你看到你这个变量是在干啥

// 工作是否完成
isWorkFinished
//超时时间
timeout

布尔类型

bool类型就是 true 和 false ,表示这个是真的,还是假的。

布尔类型最常用的就是进行比较运算,这个会非常常用,后面基本是要靠bool类型来驱动的。

数值类型是可以比较,string类型也是可以比较的。string上面也写了,包不包含。

a > b;
a < b;
a >= b;
a <= b;
a == b;
a != b;

容器类型

容器类型,是一类数据结构,为了方便我们对数据进行处理,
在英文里面,我们一般叫 Collection

容器本身没有好坏之分,只有适不适合当前场景

在学习容器时,请牢记四字箴言:

增 · 删 · 改 · 查

在 Dart 语言中,内置且最常用的容器主要有三种:

  • List:有序集合
  • Set:无序去重集合
  • Map:键值对集合

下面我们逐一来看。


List(列表)

List 是 Dart 中使用频率最高的容器,用来存放一组有顺序、可重复的数据。

1. List 的声明
List<int> numbers = [1, 2, 3];
var names = ['Tom', 'Jack'];

推荐显式声明类型,避免 List<dynamic> 带来的隐性问题。

// 不推荐
var list = [];

// 推荐
List<String> list = [];

2. 增(Add)
numbers.add(4);           // 在末尾追加
numbers.insert(0, 100);   // 在指定位置插入
numbers.addAll([5, 6]);   // 批量添加

3. 删(Delete)
numbers.remove(2);        // 删除指定值(只删第一个)
numbers.removeAt(0);      // 根据下标删除
numbers.removeLast();     // 删除最后一个
numbers.clear();          // 清空列表

注意:删除一个不存在的元素 不会报错


4. 改(Update)
numbers[0] = 999;

List 是通过下标修改的,这是它和 Set 的本质区别之一。


5. 查(Query)
numbers[0];               // 根据下标访问
numbers.contains(3);      // 是否包含某个元素
numbers.indexOf(3);       // 返回下标,不存在返回 -1
numbers.length;           // 元素个数
numbers.isEmpty;          // 是否为空

条件查询:

var result = numbers.where((e) => e > 2).toList();

6. 常见坑
  • 遍历过程中删除元素会抛异常
// 错误示例
for (var e in numbers) {
  if (e == 2) numbers.remove(e);
}

正确写法:

numbers.removeWhere((e) => e == 2);

Set(集合)

Set 用于存放不重复的数据,常见于去重、存在性判断等场景。

1. Set 的声明
Set<int> ids = {1, 2, 3};

注意:

var s = {}; // 这是 Map,不是 Set

var s = <int>{}; // 才是 Set

2. 增 / 删 / 查
ids.add(4);
ids.remove(2);
ids.contains(3);
ids.length;

Set 没有下标,因此不存在真正意义上的“改”,只能通过删除后再添加实现。


Map(映射)

Map 用于表示 键值对(Key → Value) 关系,是第二常用的容器。

1. Map 的声明
Map<String, int> scores = {
  'Tom': 90,
  'Jack': 80,
};

2. 增 / 改
scores['Lucy'] = 95;   // 新增
scores['Tom'] = 100;   // 修改(key 已存在)

3. 删
scores.remove('Jack');
scores.clear();

4. 查(重点)
scores['Tom'];               // key 不存在时返回 null
scores.containsKey('Tom');
scores.containsValue(90);
scores.keys;
scores.values;

建议在访问前判断 key 是否存在,避免空值问题。

动态类型(dynamic / Object)

Dart 是一门 强类型 + 类型推断 的语言,但它也支持动态类型,用于一些灵活或过渡场景。

dynamic

var a = 1;        // 推断为 int
dynamic b = 1;   // 动态类型


b = 'hello';     // 合法
b = true;        // 合法

dynamic 会关闭编译期类型检查,不推荐大量使用,否则容易把 Dart 写成 JS。

Object
Object obj = 'hello';
obj = 123;

Object 是所有类型的父类,但 不能直接调用子类方法,比 dynamic 更安全。

原则:

能不用 dynamic 就不用

宁愿写明确类型,也不要图省事

空安全(Null Safety)

Dart 从 2.12 开始引入了空安全,这是一个非常重要的特性。

  1. 可空类型和非空类型
String name = 'Tom';
String? nickName;

String:不能为 null

String?:可以为 null
  1. 空值访问
    nickName?.length; // 安全访问

等价于:

if (nickName != null) {
nickName.length;
}
3. 空值兜底(??)
String displayName = nickName ?? ‘匿名用户’;
4. 强制非空(!)
print(nickName!.length);

⚠️ 如果此时为 null,会直接运行时崩溃,谨慎使用。

条件控制

if / else

if (score >= 90) {
  print('优秀');
} else if (score >= 60) {
  print('及格');
} else {
  print('不及格');
}

条件必须是 bool,不能像 JS 那样随便写。

switch / case
switch (status) {
  case 0:
    print('初始化');
    break;
  case 1:
    print('进行中');
    break;
  default:
    print('未知状态');
}

注意:

每个 case 必须 break

支持 int / String / enum

循环

for 循环

for (int i = 0; i < 3; i++) {
  print(i);
}
for-in(遍历集合)
for (var item in list) {
  print(item);
}

⚠️ 遍历 List 时不要删除元素。

while / do-while

while (count > 0) {
  count--;
}
do {
  print('至少执行一次');
} while (false);
break / continue
for (var i = 0; i < 10; i++) {
  if (i == 3) continue;
  if (i == 7) break;
}

函数

函数定义

int add(int a, int b) {
  return a + b;
}

简写函数(箭头函数)

int add(int a, int b) => a + b;

可选参数

void log(String msg, {String level = 'INFO'}) {
  print('[$level] $msg');
}


log('hello');
log('error', level: 'ERROR');

可空参数

void printName(String? name) {
  print(name ?? '匿名');
}
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐