1 SDK的安装和升级

  1. brew tap dart-lang/dart
  2. brew install dart -devel

验证 :

  1. brew info dart

2 常量和变量

变量

var

未初始化时 ,为null;第一次初始化时,确定类型,一般不可更改类型,(初始化时是Int 可更改为double)

dynamic

常量

  1. final,第一次使用时被初始化<br /> const,编译时常量,隐式的final<br /> 实例变量可以是final,但不能是const;如果是类级别的 可以使用static const ,eg: static const PI = 3.1415

3 内置类型

Number(数值型)

int

double

可以用num,int,double声明
num声明的变量加入的是int型,还可以被改为 double ,但反过来int声明的变量不能再赋值double 型

String

Boolean

List(列表)

Map(键值对)

Runes(符号字符)

Symbols(标识符)

4 数值型操作

运算符:+,-,*,/,~/

~/ : 除返回整数结果

常用属性

isNaN
isEven 是否是偶数
isOdd 是否是奇数

常用方法

round():四舍五入
floor():返回不大于当前数字的最大整数
ceil():返回不小于该数字的最小整数。
toInt()
toDouble()
abs()

5 字符串

创建

使用单引号,双引号创建字符串
使用三个引号或者双引号创建多行字符串
使用r创建原始字符串

字符串操作

  • 运算符: +, *, ==, []
  • 插值表达式 : ${expression}
  • 常用属性

length
isEmpty
isNotEmpty

  • 常用方法

contains()
subString()
startsWith()
endsWith()
indexOf()
lastIndexOf()
toLowerCase()
toUpperCase()
trim():返回没有任何前导和尾随空格的字符串
trimLeft()
trimRight()
split():在指定分隔符的匹配处拆分字符串并返回子字符串列表
replaceAll()

6 布尔型

  1. 通常用在if条件判断语句里,只有布尔值'true'被视为true

7 null检查

WeChat7a1c71c4350b58a8538c3ad6e495b313.png

outgoing为null或者outgoing[a]为null或contains(b)的值为null,都会导致表达式为null

8 List(集合)和数组

可以通过[]取出对应下标的元素

常用方法

length()
add()
insert()
remove()
clear()
indexOf()
lastIndexOf()
sort()
sublist()
asMap()
forEach()
shuffle():随机打乱List里的元素的顺序

9 Map(键值对):key-value形式存储,键和值都可以是任何类型的对象,每个键只出现一次

直接声明方式创建一个Map

  1. Map game = {"name":"Switch","company":"任天堂"};

创建一个不可变的Map,在Map前面加const

  1. const Map game = const {"name":"Switch","company":"任天堂"};

10 dynamic和Object

Dart里面,一切皆对象,所有对象的父类都是Object

  • 没明确类型时的声明方式

    1. var name1 = 'abc';
    2. Object name2 = 'abc';
    3. dynamic name3 = 'abc';
  • 如果不指定类型,在debug模式下,类型会是动态的,推荐声明时指定类型 String a = ‘abc’;

  • dynamic声明时,编译器不做类型检查,如果调用了不存在的方法 ,会执行noSuchMethod(),抛出异常”NoSuchMethodError”
  • 使用as和is进行类型检查

    1. dynamic obj = <String,int>{};
    2. if (obj is Map<String,int>){
    3. obj['age'] = 20;
    4. }
    5. var map = obj as Map<String,int>;

    11 异常捕获

    抛出异常

    1. throw Exception('name error')

    捕获异常

    1. try {
    2. //捕获特定类型的异常
    3. } on OutOfLlamasException catch (e) {
    4. // 捕获特定类型的异常,但不需要这个对象
    5. } on Exception catch (e) {
    6. // 捕获所有Exception异常
    7. print('Unknown exception: $e');
    8. } catch (e) {
    9. // 捕获所有不明类型的异常
    10. print('Something really unknown: $e');
    11. }finally{
    12. //无论是否有异常都会执行
    13. }

    12 函数

  • main()函数

  • 可选参数
  • 必传参数
  • 可选参数
  • 默认参数
  • 函数作为参数传递
  • 函数作为变量

    13 声明式UI

    为了减轻开发人员在各种UI状态之间转换的编程负担,Flutter让开发人员描述当前的UI状态,并且不需要关心它是如何过渡到框架的

    14 异步编程

    Dart是基于单线程模型的语言,同步代码会阻塞程序

    Future对象来执行异步操作

    Future是dart:async包中的一个类,是一个自身的的泛型Future对象,表示一个异步操作产生的T类型的结果,如果结果的值不可用,则为Future

    Future的常见用法

  • future.then 获取Future的值与捕获Future的异常

  • 结合async,await

    • 使用async将操作放到延迟运算的队列(await)中去,
      * async标记的函数,只能由await来调用 ```objectivec String data; setData() async { data = await getData(); //getData()延迟执行后赋值给data }

    getData() async { //async关键字声明该函数内部有代码需要延迟执行 return await http.get(Uri.encodeFull(url), headers: {“Accept”: “application/json”}); //await关键字声明运算为延迟执行,然后return运算结果 }

String data1 = await getData();

  1. * 使用await,必须在有async标记的函数中运行,否则这个await会报错
  2. - future.whenComplete
  3. ![WeChat6f303969bb8756bde472bab1053b4a3e.png](https://cdn.nlark.com/yuque/0/2021/png/1994311/1620982462348-84e44539-c8f9-4db0-8790-88c061db03ea.png#clientId=uaef7af33-cd68-4&from=drop&id=m9ATZ&margin=%5Bobject%20Object%5D&name=WeChat6f303969bb8756bde472bab1053b4a3e.png&originHeight=596&originWidth=1000&originalType=binary&size=279194&status=done&style=none&taskId=u5ee56771-8ed6-4972-8cc4-0eb8be41e06)
  4. - future.timeout
  5. ![WeChat12016e42877d2db07852d30b537fc797.png](https://cdn.nlark.com/yuque/0/2021/png/1994311/1620983883767-427fbb42-b2b0-48f8-9a22-25ebbf36a183.png#clientId=uaef7af33-cd68-4&from=drop&id=u464276d3&margin=%5Bobject%20Object%5D&name=WeChat12016e42877d2db07852d30b537fc797.png&originHeight=418&originWidth=1000&originalType=binary&size=208005&status=done&style=none&taskId=u7cf41d3d-9059-4b75-9ce5-360197827ff)
  6. <a name="wZTYu"></a>
  7. #### 调用Future函数
  8. - 这个函数加入待完成的队列,并返回一个未完成的Future对象
  9. - 当这个操作结束了,Future对象返回一个值或者错误
  10. <a name="mdtcD"></a>
  11. #### FutureBuilder
  12. 构造方法包含三个参数
  13. - future:Future对象表示此构建器当前连接的异步计算;
  14. - initialData:表示一个非空的Future完成前的初始化数据
  15. - builder:AsyncWidgetBuilder类型的回调函数,是一个基于异步交互构建的Widget函数:回调函数接收两个参数,并返回一个Widget
  16. <br />回调函数接收两个参数:<br />BuildContext context<br /> AsyncSnapshot<T> snapshot 包含异步计算的信息<br />1) connectionState异步计算的连接状态:none,waiting,active,done<br />2) data 异步计算接收的最新数据<br />3) error 异步计算接收的最新错误对象<br />4) hasData 检查是否包含非空数据值<br />5) hasError 检查是否包含错误<br />
  17. <a name="C9lrY"></a>
  18. ### Dart有自己的进程(或者叫线程)机制,名叫isolate
  19. - APP的启动入口main函数就是一个isolate
  20. - 可以通过引入import 'dart:isolate'创建自己的isolate
  21. - Dartisolate之间无法直接共享内存,不同的isolate之间只能通过isolate API进行通信
  22. ![WeChat427ed8a14dfb1b91b80828c55027d4e2.png](https://cdn.nlark.com/yuque/0/2021/png/1994311/1620985062179-92aff01a-fd05-4e8f-a10e-fd40f5562853.png#clientId=uaef7af33-cd68-4&from=drop&id=u2bb63995&margin=%5Bobject%20Object%5D&name=WeChat427ed8a14dfb1b91b80828c55027d4e2.png&originHeight=574&originWidth=1000&originalType=binary&size=349241&status=done&style=none&taskId=u190c7dce-fa42-4bc0-9609-e726bae0b68)<br />![WeChat8ffebd5e4188f52100af9ee4d3bd8f51.png](https://cdn.nlark.com/yuque/0/2021/png/1994311/1620985127131-cdb64ceb-bf90-4fec-8e5d-38b349fa9222.png#clientId=u807f32d1-bc2a-4&from=drop&id=ue8d10519&margin=%5Bobject%20Object%5D&name=WeChat8ffebd5e4188f52100af9ee4d3bd8f51.png&originHeight=466&originWidth=1000&originalType=binary&size=305689&status=done&style=none&taskId=uf629bc11-93be-4ce7-a4d8-4877f3af688)
  23. <a name="XZONX"></a>
  24. ### Dart的消息循环机制(event loop) --两个队列
  25. <a name="nhYED"></a>
  26. #### event queue
  27. I/Omouse eventsdrawing eventstimersisolate之间的message等。任意isolate中新增的eventI/Omouse eventsdrawing eventstimersisolatemessage)都会放入event queue中排队等待执行
  28. <a name="qJmMH"></a>
  29. #### microtask queue
  30. 只在当前isolate的任务队列中排队,优先级高于event queue
  31. <a name="Vl1iU"></a>
  32. ## 15 继承,接口实现和混合
  33. - 继承(extends)
  34. - 接口实现(implements)
  35. - 混合(mixins):在类中混入其他功能
  36. 把自己的方法提供给其他类使用,但不需要成为其他类的父类<br /> 要使用mixins,需要用关键字with来复用类中的代码<br /> 优先级(从高到低):本类->mixins->extends->implements
  37. <a name="oO1Xi"></a>
  38. ## 16 dart 的构造函数
  39. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1994311/1620982358817-f9e3f33b-d5d4-4c4b-848c-365d65fd0178.png#clientId=uaef7af33-cd68-4&from=paste&height=347&id=uae4ca56a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=694&originWidth=2310&originalType=binary&size=595940&status=done&style=none&taskId=u7d73bcb7-e7ce-414b-8867-5fa56b59c36&width=1155)<br />
  40. <a name="E9tCD"></a>
  41. ## 17 泛型
  42. <a name="yO8OM"></a>
  43. ### 泛型方法
  44. 泛型方法可以约束一个方法使用同类型的参数、返回同类型的值,可以约束里面的变量类型。
  45. ```dart
  46. T getData<T> (T val) {
  47. return val;
  48. }
  49. getData<String>('123');
  50. getData<int>(123);
  51. getData<double>(123);
  52. // getData<bool>(123); // Error: The argument type 'int' can't be assigned to the parameter type 'bool'.

泛型类

声明泛型类,比如声明一个 Array 类,实际上就是 List 的别名,而 List 本身也支持泛型的实现

  1. class Array<T> {
  2. List _list = new List<T>();
  3. Array();
  4. void add<T>(T value) {
  5. this._list.add(value);
  6. }
  7. get value{
  8. return this._list;
  9. }


}
使用泛型类

  1. print('----- 泛型类 ------');
  2. List l1 = new List<String>();
  3. // l1.add(12); // type 'int' is not a subtype of type 'String' of 'value'
  4. l1.add('asd');
  5. Array arr = new Array<String>();
  6. arr.add('aa');
  7. arr.add('bb');
  8. // arr.add(123); // type 'int' is not a subtype of type 'String' of 'value'
  9. print(arr.value);
  10. Array arr2 = new Array<int>();
  11. arr2.add(1);
  12. arr2.add(2);
  13. print(arr2.value);

泛型接口

声明了一个 Storage 接口,然后 Cache 实现了接口,能够约束存储的 value 的类型:

  1. abstract class Storage<T>{
  2. Map m = new Map();
  3. void set(String key, T value);
  4. void get(String key);
  5. }
  6. class Cache<T> implements Storage<T> {
  7. @override
  8. Map m = new Map();
  9. @override
  10. void get(String key) {
  11. print(m[key]);
  12. }
  13. @override
  14. void set(String key, T value) {
  15. print('set successed!');
  16. m[key] = value;
  17. }


}
使用泛型接口实现的类:

  1. print('----- 泛型接口 ------');
  2. Cache ch = new Cache<String>();
  3. ch.set('name', '123');
  4. // ch.set('name', 1232); // type 'int' is not a subtype of type 'String' of 'value'
  5. ch.get('name');
  6. Cache ch2 = new Cache<Map>();
  7. // ch2.set('name', '23'); // type 'String' is not a subtype of type 'Map<dynamic, dynamic>' of 'value'
  8. ch2.set('ptbird', {'name': 'pt', 'age': 20});
  9. ch2.get('ptbird');