dart|dart 基础

语言特性

  • 在Dart中,一切都是对象,一切对象都是class的实例,哪怕是数字类型、方法甚至null都是对象,所有的对象都是继承自Object
  • 尽管 Dart 是强类型语言,但是在声明变量时指定类型是可选的,因为 Dart 可以进行类型推断。
  • Dart 支持泛型,比如 List(表示一组由 int 对象组成的列表)或 List(表示一组由任何类型对象组成的列表)。
// 声明数组,里面包含< DeviceHealthModel > List dataSource = [];

  • 跟Java不同的是,Dart没有public protected private等关键字,如果某个变量以下划线(_)开头,代表这个变量在库中是私有的
  • Dart中变量可以以字母或下划线开头,后面跟着任意组合的字符或数字
变量和常量
  • 创建变量
var age = 19; // 类型推断为int dynamic name1 = '小菊'; // 未知类型 String name2 = '小菊'; // 指定类型为String List ages = [1, 2, 3, 4]; // 声明int数组 int myage; // 未初始化的变量, 默认值为null

  • 创建常量 final和const
  • 【dart|dart 基础】如果一个变量的值不再修改,则使用final或者const代替var
    一个final变量只能赋值一次;一个const变量是编译时常量,const变量默认为final变量。
    final修饰的顶级变量或类变量在第一次声明的时候就需要初始化。
void main(List args) { final String name = "小菊"; const age = 18; // 声明时必须初始化, 否则报错 The constant 'age' must be initialized. //The name 'deviceName' is already defined. }

  • 顶层final变量与类变量在首次访问时执行初始化。需要注意的是,实例变量可以为final,但是不能是const
class DeviceHealth extends StatefulWidget { @override final a ; // final修饰的实例变量可以在下面初始化的时候赋值static const b = ""; //常量如果是类里的,请使用 static constDeviceHealth({ this.a = "", // this.a = "a", // 无法二次修改 GlobalKey<_DeviceHealthState> key, }) : super(key: key); State createState() { // TODO: implement createState return null; } }class _DeviceHealthState extends State { @override Widget build(BuildContext context) { // TODO: implement build throw UnimplementedError(); } }

  • const 关键字不仅仅可以用来定义常量,还可以用来创建常量值,该常量值可以赋予给任何变量
void main(List args) { var a = const [1, 2]; // const创建 常量列表 a = [2]; // 可以被重新赋值final b = const [1, 2]; b = [2]; // final 和 const定义 还是不可以被重新赋值 }

  • const 只能被赋值const类型, 无法被final 或其他类型赋值.
数据类型
  • numbers
    Dart支持两种类型的数字
void main(List args) { var a = 1; // int var b = 1.0; // double int c = int.parse("1"); // string 转 int double d = double.parse("1.1"); // string 转 double String str1 = 1.toString(); // 数字转字符串 String str2 = 3.1415926.toStringAsFixed(2); // 输出3.14 }

  • String
void main(List args) { String str1 = "sdhsadkjhas"; // 创建字符串 String str2 = "fnjdshuic\""; //\用于转义 print("字符串1为 $str1"); // $ 格式化 print("字符串2为 ${str1 + str2}"); // ${} 插入表达式 , + 拼接字符串 String str3 = ''' 创建多行字符串 '''; print(str1.length); // 字符串长度 print(str1.isEmpty); // 字符串是否为空 str1.contains("sss"); // 字符串是否包含另外一个字符串 String str4 = str1.substring(1,4); // 字符串截取 bool a = str4.startsWith("s"); // 字符串是否以xxx开头 int b = str4.indexOf("sss"); // 第一次某个字符串的下标 int c = str4.lastIndexOf("sss"); // 最后一次出现某个字符串的下标 str4.toLowerCase(); // 字符串转小写 str4.toUpperCase(); // 字符串转大写 str4.trim(); // 字符串清除空格 str4.trimLeft(); // 清除最左边的空格 str4.trimRight(); // 清除最右边的空格 List strList = str4.split("."); // 字符串分割后数组str4.replaceAll(new RegExp(r'e'), 'é'); // 字符串替换 str4.replaceAll("a", "s"); }

  • booleans
true 和 false

  • list
void main(List args) { List list = [10, 7, 23]; //创建一个int类型的list var animal = new List(); animal.add('dog'); // 添加 animal.addAll(['cat', 'cat']); // 从另外一个数组添加多个 print(animal.length); // 获取List的长度 print(animal.first); // 第一个 print(animal.last); // 最后一个 print(animal[0]); // 索引获取 print(animal.indexOf('cat')); // 查找某个元素的索引 print(animal.removeAt(0)); // 删除指定位置,返回删除的元素 animal.remove('cat'); // 删除指定元素,成功返回true,失败返回false, 如果集合里面有多个, 只会删除集合中第一个改元素 animal.removeLast(); // 删除最后一个,返回删除的元素 animal.removeRange(0, 2); // 删除 [0, 2) 内元素 animal.removeWhere((item) => item.length > 3); // 删除指定条件的元素(这里是元素长度大于3) animal.clear(); // 删除所有 animal.sort(); // 按照ASCII码排序 animal.sublist(1,3); // 获取子数组[) 左开右闭 }

  • map
void main(List args) { Map animal1 = {}; // 创建空map var animal2 = new Map(); // 创建空map// 如果Key 不存在于 Map 中 取值则会返回一个 nullanimal1["a"] = "1"; // 赋值 animal1.remove("a"); // 移除 animal1.containsKey("a"); // 是否存在某个key animal1.containsValue("b"); // 是否存在某个value print(animal1.keys); // 打印所有的key print(animal1.values); // 打印所有的value animal1.clear(); // 清空map animal1.isEmpty; // 检测是否为空 animal1.addAll({"c": "2", "d" : "3"}); // 从另外一个map 添加 }

运算符 operators
描述 操作符
一元后缀 expr++ expr-- () [] . ?.
一元前缀 expr !expr ~expr ++expr --expr
乘除法 * / % ~/
加减法 + -
位运算 << >>
按位与 &
按位或 |
按位异或 ^
逻辑与 &&
逻辑或 ||
关系和类型测试 >= > <= < as is is!
相等判断 == !=
空判断 ??
条件表达式 expr1 ? expr2 : expr3
赋值 = *= /= ~/= %= += -= <<= >>= &= ^= = ??=
级联 ..
  • 挑一些区别性的
操作符 作用
is 判断一个变量是不是某个类型的数据
is! 判断变量不是某个类型的数据
as 强制转换
/ 除法, 可能带小数点
~/ 是取整运算符
??= 如果 ??= 运算符前面的变量为null,则赋值,否则不赋值
.. 同一个对象上连续调用多个对象的变量或方法
  • is, is!
    (判断一个变量是不是某个类型的数据)
String a = "1"; print(a is String); // true print(a is! String); // false

  • as
    (强制转换)
dynamic b = 1; // 未知类型 print(b as int); // 强制转换int

  • /
    (除法, 可能带小数点)
var a = 100.0; a = a / 2; print(a); // 50.0

  • ~/
    (取整)
var a = 100.0; int c = a ~/ 3; // 必须用int 接收 print(c); // 33

  • ??=
    (如果 ??= 运算符前面的变量为null,则赋值,否则不赋值)
var str1 = "小菊"; String str2; str1 ??= "孝举"; // 小菊 str2 ??= "孝举"; // 孝举 print(str1); print(str2);

  • ..
    (同一个对象上连续调用多个对象的变量或方法)
void main() { var str1 = "小菊"; str1.toLowerCase()..replaceAll("s", "ss"); // 连续调用多个对象方法. }

控制流程语句
  • if else
    Dartif语句中的条件必须是一个布尔值,不能是其它类型. (iOS中也可以用整型表示, 这里不行)
if (3 > 1) { print("大"); } else { print("小"); }

  • for 循环
  1. 标准for循环(可以使用)
for (var i = 0; i < 5; i++) { print(" $i"); }

  1. for-in 循环
数组遍历
var numbers = [1,2,3,4,5]; for (var number in numbers) { print(number); }

  1. for-each
    数组遍历
var numbers = [1,2,3,4,5]; numbers.forEach((number) => print(numbers) );

字典 key-value遍历, 请使用forEach.
var numbers = {"a": "1", "b": "2"}; numbers.forEach((key, value) => { print(value), print(key), });

  • while 和 do-while 循环 (和原生语言一样)
  • break 和 continue (和原生语言一样)
  • switch 和 case
void main() { int a = 1; switch (a) { mark: case 0: print("0"); break; case 1: print("1"); continue mark; // Continue使用在被标记为mark的子句中 case 2: print("2"); break; } }// 输出10

异常 Exceptions
try { breedMoreLlamas(); } on OutOfLlamasException { // 指定异常 buyMoreLlamas(); } on Exception catch (e) { // 其它类型的异常 print('Unknown exception: $e'); } catch (e) { // // 不指定类型,处理其它全部 print('Something really unknown: $e'); }

函数 Function 类 Class
  • 类的基本构成
    构造方法和实例变量
    类定义中所有的变量, Dart语言都会隐式的定义 setter 方法,针对非空的变量会额外增加 getter 方法。
typedef void ReConnectButtonClick(); class ReConnectWifiView extends StatefulWidget { String deviceName; // 实例变量 ReConnectButtonClick reConnectButtonClick; // 实例变量// 初始化方法1 ReConnectWifiView({ this.deviceName = "", this.reConnectButtonClick, GlobalKey<_ReConnectWifiViewState> key, }) : super(key: key); // iOS方式的初始化方法2, 不推荐 扩展性差) 等同于下面的初始化3 // ReConnectWifiView(this.deviceName, this.reConnectButtonClick); // iOS方式的初始化方法3, 不推荐 扩展性差) // ReConnectWifiView(String deviceName, ReConnectButtonClick reConnectButtonClick) { //this.deviceName = deviceName; //this.reConnectButtonClick = reConnectButtonClick; // }// 命名式构造函数 // ReConnectWifiView.method1(String deviceName, ReConnectButtonClick reConnectButtonClick) { //this.deviceName = deviceName; //this.reConnectButtonClick = reConnectButtonClick; // }@override State createState() { // TODO: implement createState return new _ReConnectWifiViewState(); } } class _ReConnectWifiViewState extends State { @override Widget build(BuildContext context) { // TODO: implement build throw UnimplementedError(); } }

  • 获取对象的类型
    可以使用Object对象的runtimeType属性在运行时获取一个对象的类型
void main() { int a = 1; print("这个类型是 ${a.runtimeType}"); }输出: 这个类型是 int

  • 静态变量&&静态方法
class Mine{ @overridestatic const money = 17; // 定义静态变量, 在其首次被使用的时候才被初始化。 static String sayHello() { return "hello"; } } class You { _say() { Mine.sayHello(); // Mine类调用方法 } }

  • 继承(extends)
    Dart 语言中,子类不会继承父类的命名构造函数。如果不显式提供子类的构造函数,系统就提供默认的构造函数
    如果想要子类也拥有一个父类一样名字的构造函数,必须在子类是实现这个构造函数。
class Person { String firstName; Person.fromJson(Map data) { print('in Person'); } }由于Employee类没有默认构造方法,只有一个命名构造方法fromJson,所以在Employee类继承Person类时, 需要调用父类的fromJson方法做初始化, 而且必须使用Employee.fromJson(Map data) : super.fromJson(data)这种写法,class Employee extends Person { Employee.fromJson(Map data) : super.fromJson(data) { print('in Employee'); } }

  • set get 方法
class ReConnectWifiView extends StatefulWidget { String deviceName; ReConnectButtonClick reConnectButtonClick; ReConnectWifiView({ this.deviceName = "", this.reConnectButtonClick, GlobalKey<_ReConnectWifiViewState> key, }) : super(key: key); // set方法 set xiaojuName(String value) { deviceName = value + deviceName; } // get 方法 String get myName { return deviceName + ""; }@override State createState() { // TODO: implement createState return new _ReConnectWifiViewState(); } }

  • 类-抽象类
abstract class Person { void work(); // 抽象方法 void sayhello() { // 普通方法} } class Me extends Person { @override// 抽象类的子类必须实现抽象方法 void work() { //提供一个实现,所以在这里该方法不再是抽象的 } }

  • noSuchMethod()
    如果调用了对象上不存在的方法或实例变量将会触发 noSuchMethod 方法,你可以重写noSuchMethod 方法来追踪和记录这一行为
void main() { TestMethod test = new TestMethod(); dynamic f = test.foo; // Invokes `Object.noSuchMethod`, not `TestMethod.noSuchMethod`, so it throws. f(42); }class TestMethod { // 除非你重写noSuchMethod,否则使用不存在的成员会导致NoSuchMethodError @override void noSuchMethod(Invocation invocation) { print('You tried to use a non-existent member: ' + '${invocation.memberName}'); } dynamic foo(); }

  • 类-扩展一个类的方法 Extension (in Dart 2.7)
    当您使用他人的API或实现广泛使用的库时,更改API通常是不切实际或不可能的。 但是您可能仍想添加一些功能。可以使用这个添加方法.
    类似iOS中的类别, 扩张一个类的方法, 不需要加入到class类的代码中.
class Mine{ @override// 抽象类的子类必须实现抽象方法_extensionTest() { this.doneAction(); } }// 为Mine 这个类扩展方法, MineExtension为扩展类名(随便取), doneAction扩展方法 extension MineExtension on Mine { void doneAction() { print("Ssss"); } }

  • 枚举
  1. enum
enum Color { red, green, blue }

  1. 和iOS一样, 枚举值默认从0开始, 上面依次为
Color.red.index == 0 Color.green.index == 1 Color.blue.index == 2

  1. 获取枚举中所有值的列表
List colors = Color.values; assert(colors[2] == Color.blue);

  • Mixin
    Mixin 是一种在多重继承中复用某个类中代码的方法模式。
class Dog { String name; sayWang() { print("说汪汪汪"); } } class Cat { sayMiao() { print("说喵喵喵"); } } // 使用with 关键字, 使得person 也能调用Dog, Cat方法和变量 class Person with Dog, Cat { say() { Person().sayWang(); // 使用dog方法. print(Person().name); // 使用dog变量 Person().sayMiao(); print("我也会说汪汪汪, 也会喵喵喵"); } }

库和可见性 异步支持 asyncawait关键字用于实现异步编程,并且让你的代码看起来就像是同步的一样。
await表达式中, 表达式 的值通常是一个 Future 对象;如果不是,那么这个值会自动转为Future
// 做异步等待, 直到await 返回数据 Future _receiveCloudedgeData() async { dynamic result; try { result = await WYChannel.mineDataChannel .invokeMethod(WYChannel.chimeSettingMethod); } on PlatformException { result = "error"; } if (result is String) { // print(result); GlobalConfig.languageCode = result; }

import 'dart:async'; import 'package:http/http.dart' as http; // 返回string Future getNetData() async{ http.Response res = await http.get("http://www.baidu.com"); return res.body; }main() { getNetData().then((str) { print(str); }); }

    推荐阅读