当前位置: 首页 > news >正文

Dart | 安装基础环境和快速入门(保姆级教程)

Dart 是一种由 Google 开发的客户端优化的编程语言,适用于移动、Web、服务器和物联网(IoT)等领域的开发。它是 Flutter 框架的官方语言,用于构建高性能、高保真的跨平台应用。

一、安装 Dart SDK

  • 访问官网: 前往 Dart 官方网站:https://dart.dev
  • 百度网盘:
    链接: https://pan.baidu.com/s/1Zeq9SdRa-zkVja3Z80V1fA 提取码: 5qpx

一直next即可

验证sdk:

dart --version

二、快速入门 

 安装Dart插件:

1.基础语法

  • 入口函数: 每个 Dart 程序都必须有一个 main() 函数,它是程序执行的起点。
  • 变量与类型:
    • var: 声明变量,类型由编译器推断。
    • String: 字符串类型。
    • int: 整数类型。
    • double: 浮点数类型。
    • bool: 布尔类型 (truefalse)。
    • dynamic: 可以存储任何类型的值(不推荐过度使用,会失去类型安全)。
    • final / const: 声明不可变的变量。final 在运行时赋值一次,const 在编译时常量。
1. 声明变量

有几种方式可以声明变量:

  • 使用 var 关键字 (推荐用于局部变量):

    • var 允许编译器根据你第一次赋的值来推断变量的类型。
    • 一旦推断出类型,该变量就不能再被赋予其他类型的值。
    void main() {var name = 'Alice'; // 推断为 String 类型var age = 25;       // 推断为 int 类型var height = 1.75;  // 推断为 double 类型// name = 100; // 错误!不能将 int 赋值给一个 String 类型的变量name = 'Bob'; // 正确!可以赋值给同为 String 类型的值
    }
  • 显式指定类型:

    • 你可以明确地写出变量的数据类型,这使得代码意图更清晰,也避免了类型推断可能带来的歧义。
    void main() {String name = 'Charlie';int age = 30;double price = 9.99;bool isActive = true;// 或者先声明后赋值String city;city = 'Beijing';
    }
  • 使用 dynamic 关键字 (谨慎使用):

    • dynamic 类型的变量可以存储任何类型的值,并且可以在运行时改变其类型。
    • 注意: 使用 dynamic 会失去 Dart 的类型安全检查,容易在运行时引发错误,应尽量避免,除非有特殊需求。
    void main() {dynamic something = 'Hello';print(something.runtimeType); // Stringsomething = 42;print(something.runtimeType); // intsomething = true;print(something.runtimeType); // bool
    }
  • 使用 Object?:

    • Object 是所有 Dart 类的根类。Object? 表示可以是任何对象,也可以是 null
    • 它比 dynamic 更安全,但使用时需要进行类型检查或转换。
2. 变量的命名规则
  • 名称必须以字母或下划线 (_) 开头。
  • 后续字符可以是字母、数字、下划线或美元符号 ($)。
  • 区分大小写(myVariable 和 myvariable 是不同的)。
  • 不能使用 Dart 的保留关键字(如 intclassvoid 等)作为变量名。
  • 推荐使用 驼峰命名法 (camelCase),例如:userNameaccountBalance

Dart 常量 (Constants)

常量是值在初始化后不能被改变的变量。Dart 提供了两种创建常量的方式,它们的使用场景和约束不同。

1. final 关键字
  • 含义: 一个 final 变量只能被赋值一次
  • 赋值时机: 可以在运行时确定其值。也就是说,它的值可以是程序执行过程中计算出来的。
  • 作用域: 通常用于声明在对象的生命周期内不应改变的变量,或者在函数内声明一个不应被修改的值。
void main() {// 在声明时赋值final String language = 'Dart';// language = 'Java'; // 错误!不能重新赋值// 在运行时赋值(例如,获取当前时间)final DateTime now = DateTime.now();print(now); // 每次运行程序,值都不同,但赋值后就不能再改// final 变量也可以在构造函数中初始化(在类中)
}
2. const 关键字
  • 含义const 代表编译时常量
  • 赋值时机: 其值必须在编译时就能完全确定。它不能依赖于运行时才能知道的值。
  • 深层含义const 不仅是一个值,它还代表一个规范化的对象。这意味着,两个具有相同 const 构造的表达式会引用内存中的同一个对象
void main() {// 基本数据类型的编译时常量const int maxUsers = 100;const String appName = 'My App';// 使用 const 构造函数创建对象const List<int> numbers = [1, 2, 3]; // 使用 const 列表字面量const Map<String, int> scores = {'Alice': 95, 'Bob': 87};// 这是允许的,因为 DateTime.utc 是一个 const 构造函数,且参数是编译时常量const DateTime compileTime = DateTime(2025, 1, 1);// 这是错误的!DateTime.now() 的值在运行时才能知道// const DateTime now = DateTime.now(); // 编译错误// 演示 const 的“规范性”const List<int> list1 = [1, 2, 3];const List<int> list2 = [1, 2, 3];print(identical(list1, list2)); // true,它们是同一个对象final List<int> list3 = [1, 2, 3];final List<int> list4 = [1, 2, 3];print(identical(list3, list4)); // false,它们是两个不同的对象
}
final vs const 关键区别总结
特性finalconst
赋值时机运行时 (Runtime)编译时 (Compile-time)
值的来源可以是运行时计算的结果必须是编译时已知的常量
对象规范性每次 final 声明都会创建新对象相同的 const 表达式引用同一个对象
性能略低(运行时赋值)更高(编译时确定,可复用)
何时使用值在初始化后不应改变,但初始化依赖运行时值是固定的,且希望在编译时确定和优化
  • 字符串:
    • 可以用单引号 (') 或双引号 (")。
    • 字符串插值:'Hello, $name!' 或 'Hello, ${name.toUpperCase()}!'
1. 创建字符串

你可以使用单引号 (') 或双引号 (") 来创建字符串字面量。

void main() {String singleQuote = 'Hello, Dart!';String doubleQuote = "Hello, World!";// 两种方式效果完全相同print(singleQuote); // Hello, Dart!print(doubleQuote); // Hello, World!// 引号嵌套:如果字符串内需要包含引号,可以使用不同类型的引号包围String withSingle = "He said, 'Hello!'"; String withDouble = 'She said, "Hi!"'; // 或者使用反斜杠 \ 进行转义String escaped1 = 'It\'s a sunny day.';String escaped2 = "She said, \"Hello!\"";
}
2. 多行字符串

当你的字符串内容跨越多行时,可以使用以下两种方式:

  • 三重引号 ('''"""):

    • 使用三个单引号或三个双引号。
    • 字符串内的换行和空格会被原样保留。
    String multiLine1 = '''
    This is line one.
    This is line two.This line has leading spaces.
    ''';String multiLine2 = """
    JSON example:
    {"name": "Alice","age": 30
    }
    """;
  • 相邻字符串拼接:

    • 将多个字符串字面量写在一起,Dart 会自动将它们连接成一个字符串。
    • 这种方式不会保留字面量之间的换行符。
    String concatenated = 'This is the first part ''and this is the second part ''on the same line.';
    // 结果: "This is the first part and this is the second part on the same line."
3. 字符串插值 (String Interpolation)

这是 Dart 字符串最强大的特性之一。你可以在字符串中嵌入变量或表达式的值。

  • 语法: 使用 $variableName 或 ${expression}
  • 如果只是插入一个简单的变量名,使用 $ 加变量名即可。
  • 如果要插入一个表达式、属性或更复杂的逻辑,必须用 ${} 包裹。
void main() {String name = 'Bob';int age = 25;double height = 1.80;// 插入变量String greeting = 'Hello, $name!'; print(greeting); // Hello, Bob!// 插入表达式String info1 = '$name is ${age + 1} years old next year.'; print(info1); // Bob is 26 years old next year.// 调用方法或访问属性String info2 = 'The length of the name is ${name.length}.'; String info3 = '${name.toUpperCase()} is shouting!'; print(info2); // The length of the name is 3.print(info3); // BOB is shouting!// 当变量名后紧跟字母数字字符时,必须用 {} 包裹String tricky = 'His name is ${name}y'; // 正确: Buby// String wrong = 'His name is $namey'; // 错误!编译器会找名为 'namey' 的变量
}
4. 字符串拼接

有几种方式可以将两个或多个字符串连接起来。

  • 使用 + 操作符:

    String firstName = 'John';
    String lastName = 'Doe';
    String fullName = firstName + ' ' + lastName; // John Doe
  • 使用相邻字符串 (如上所述):

    String sentence = 'Welcome to ' 'Dart programming!'; // Welcome to Dart programming!
  • 使用字符串插值:

    String fullName = '$firstName $lastName'; // 更简洁
  • 使用 StringBuffer 类 (推荐用于大量拼接):

    • 当你需要进行大量的字符串拼接操作时(例如在循环中),使用 + 会产生很多中间的字符串对象,效率较低。
    • StringBuffer 是一个可变的缓冲区,专门为此优化。
    void main() {StringBuffer buffer = StringBuffer();buffer.write('Hello');buffer.write(' ');buffer.write('World');buffer.writeln('!'); // write + 换行buffer.writeAll(['a', 'b', 'c'], '-'); // 用 '-' 连接并写入String result = buffer.toString(); // 转换为最终的 Stringprint(result);/*Hello World!a-b-c*/
    }

Dart 字符串的常用属性和方法

String 类提供了丰富的 API 来操作和查询字符串。

常用属性
  • length: 返回字符串的长度(字符数)。
  • isEmpty: 如果字符串为空(长度为0),返回 true
  • isNotEmpty: 如果字符串不为空,返回 true
String emptyStr = '';
String text = 'Dart';print(text.length);     // 4
print(emptyStr.isEmpty); // true
print(text.isNotEmpty); // true
常用方法
  • 大小写转换:

    • toUpperCase(): 转换为大写。
    • toLowerCase(): 转换为小写。
    print('hello'.toUpperCase()); // HELLO
    print('WORLD'.toLowerCase()); // world
  • 查找和判断:

    • contains(Pattern pattern, [int startIndex = 0]): 判断是否包含某个子串或模式。
    • startsWith(Pattern pattern, [int index = 0]): 判断是否以某个模式开头。
    • endsWith(Pattern other): 判断是否以某个模式结尾。
    • indexOf(String needle, [int start = 0]): 返回子串第一次出现的索引,未找到返回 -1。
    String email = 'user@example.com';
    print(email.contains('@'));           // true
    print(email.startsWith('user'));      // true
    print(email.endsWith('.com'));        // true
    print(email.indexOf('example'));      // 5
  • 截取和分割:

    • substring(int start, [int? end]): 提取从 start 到 end(不包括)的子串。
    • split(Pattern pattern): 根据分隔符拆分成一个 List<String>
    String path = '/home/user/documents/file.txt';
    print(path.substring(1, 5));         // home
    print(path.split('/'));              // ['', 'home', 'user', 'documents', 'file.txt']
    print('a,b,c'.split(','));           // ['a', 'b', 'c']
  • 去除空白:

    • trim(): 去除字符串首尾的空白字符(空格、制表符、换行符等)。
    • trimLeft() / trimRight(): 分别去除左侧/右侧空白。
    String messy = '  Hello Dart  \n';
    print(messy.trim()); // 'Hello Dart'
  • 替换:

    • replaceAll(Pattern from, String replace): 将所有匹配项替换为新字符串。
    String text = 'I love cats. Cats are great.';
    print(text.replaceAll('Cats', 'Dogs')); // I love dogs. Dogs are great.
  • 其他:

    • compareTo(String other): 按字典顺序比较两个字符串,返回负数、0或正数。
    • codeUnitAt(int index): 获取指定索引处的 UTF-16 码元。

重要注意事项

  1. 不可变性 (Immutability): Dart 的 String 是不可变的。任何看起来“修改”了字符串的方法(如 toUpperCase, trim, replaceAll)实际上都返回了一个新的字符串对象,而原始字符串保持不变。

    String original = 'hello';
    String upper = original.toUpperCase(); 
    print(original); // hello (未改变)
    print(upper);    // HELLO (新对象)
  2. UTF-16 编码: Dart 字符串基于 UTF-16。对于大多数基本拉丁字母,一个字符对应一个码元。但对于一些特殊字符(如某些 emoji 或 Unicode 码点大于 U+FFFF 的字符),可能需要两个码元(代理对)。因此,length 属性返回的是码元的数量,而不是直观的“字符”数量。如果需要精确的字符计数,可以使用 characters 包。

    # pubspec.yaml
    dependencies:characters: ^1.2.1
    import 'package:characters/characters.dart';void main() {String emojiStr = '👨‍👩‍👧‍👦'; // 家庭 emojiprint(emojiStr.length); // 可能输出 7 或 8 (码元数)print(emojiStr.characters.length); // 输出 1 (正确的字符数)
    }
  • 集合 (Collections):
    • List: 有序集合,类似数组。var list = [1, 2, 3];
    • Set: 无序且唯一元素的集合。var set = {1, 2, 3};
    • Map: 键值对集合。var map = {'name': 'Alice', 'age': 30};
  • 控制流:
    • if / else
    • for 循环 (for (var i = 0; i < 5; i++)) 和 for-in 循环 (for (var item in list))
    • while / do-while
http://www.dtcms.com/a/569867.html

相关文章:

  • 网站购买域名八年级信息网站怎么做
  • 海阳建设局网站php开源公司网站
  • 山东手机网站建设标致品牌设计公司
  • 私密浏览器下载网站建设与优化推广方案内容
  • React学习笔记
  • 设备如何“开口说话”
  • 信息论(二):符号的可预测性与压缩
  • 网站与客户端的区别吗可以安装wordpress
  • git 高级命令模式典型应用--“同步云端 + 清理垃圾分支”的一键命令
  • 天助网的网站百度排行榜明星
  • Kanass零基础学习,如何进行版本管理
  • 深圳网站建设公司多吗英国做deal的网站
  • C++ 算法题中链表的操作技巧总结 链表 模拟 力扣 2. 两数相加 题解 每日一题
  • CI/CD 是如何改变软件世界的?
  • 企业级Agent智能体(智能小秘)之MCP服务认证实现
  • 无极商城网站建设什么是网络营销策划书
  • 将地球上的距离转化为经纬度差
  • 华为OD机试双机位A卷 - 叠积木 (C++ Python JAVA JS GO)
  • Windows 2008 如何安装IIS?
  • wordpress後台建站赚钱项目
  • Day57 | 一文详解ThreadLocal
  • 快速判断地图上的点是否在多边形内部
  • 网站文章的作用邵阳市今天新闻
  • C#设计模式 单例模式实现方式
  • 网站是怎么搭建的简单个人博客模板网站
  • 【题解】洛谷 P10083 [GDKOI2024 提高组] 不休陀螺 [思维 + 树状数组 + st 表]
  • C语言字符串操作:手写strlen+常用库函数解析
  • 自己可以创建公司网站吗赣州网站制作培训
  • 百度优化排名软件seo交流
  • 链表相关的算法题(1)