Flutter开始干系列-Dart2

直接开始干,没有为何~html

零、注释

首先来个很重要的注释,代码没有注释,命名又不规范,那将极度糟糕。Dart 分单行、多行、文档注释三种。express

  • 单行注释
//我是单行注释
复制代码
  • 多行注释
/*
多行注释
多行注释
多行注释
*/
复制代码
  • 文档注释 文档注释是由 /// 或 /** 开始的多行或单行注释。在连续的行上使用 /// 的效果等同于多行注释。

在一段文档注释中,Dart 编译器忽略全部除括号内的文本。你可使用括号来引用类、方法、属性、顶级变量、函数和参数。括号中的名字会在被文档化程序元素的词法范围内解析。json

/// A domesticated South American camelid (Lama glama).
///
/// Andean cultures have used llamas as meat and pack
/// animals since pre-Hispanic times.
class Llama {
  String name;

  /// Feeds your llama [Food].
  ///
  /// The typical llama eats one bale of hay per week.
  void feed(Food food) {
    // ...
  }

  /// Exercises your llama with an [activity] for
  /// [timeLimit] minutes.
  void exercise(Activity activity, int timeLimit) {
    // ...
  }
}
复制代码

1、变量/常量

变量定义

var name = 'jk'; //定义了字符串 name 赋予初值 jk
int _age = 25; //定义了整数 age 赋予初值 25
int sex; //定义了整数 sex 默认初值 null
复制代码

敲黑板api

  1. 定义变量可使用 var 和 具体数据类型
  2. Dart 没有 public、private 等限定符,有 @protected 注解,带 _ 就是私有(不管属性 仍是函数 亦或是类),反之则不是
  3. 通常局部变量使用 var ,私有成员变量使用具体变量类型
  4. dynamic 动态类型,编译期不执行类型检查

常量定义

const String name = 'jk'; // 声明字符串常量 name  赋予初值 jk
final String api = 'www.baidu.com'; 声明字符串常量 api  赋予初值 www.baidu.com
static const port = '8080'; // 声明字符串静态常量 port  赋予初值 8080
复制代码

敲黑板数组

  1. const 编译时肯定,const 不能是实例值
  2. final 第一次运行时肯定
  3. const 在类中的话,就必须定义为 static const

2、数据类型

number

Dart 仅有2种数字类型bash

  • int 整数值 没有long
  • double 64位(双精度)浮点数 没有float
  • number 类型不能当作 string 使用,也不能直接和 string 相加,须要先toString

strings

  • String 能够用" "或者 ' ' 来声明,推荐使用 ' ',由于它能够套 " ",不然须要转义
  • ''' ''' 或 """ """ 能够申明一个多行字符串
  • 在字符串中能够用表达式 ${expression},也能够用 + 号来拼接字符串

booleans

  • bool 真 -> true,假 -> false

lists(也称为数组arrays)

在Dart中,数组是List对象,所以它们都称为列表。markdown

// 如下都能定义一个列表
var list = [];
List list = List();

// 静态常量列表
var constantList = const [1, 2, 3];
// constantList[1] = 1; // 取消注释将会报错

复制代码

敲黑板dom

a. Dart 2.3 增长操做符 ... 和 ...? ,提供一种将多个元素插入 List 的简便方法异步

//经过 ... 把 list 中全部元素 add 到 list2
var list = [1, 2, 3];
var list2 = [0, ...list];
assert(list2.length == 4);

//若是 list 可能为 null ,则经过 ...? 把 list 中全部元素 add 到 list2
var list;
var list2 = [0, ...?list];
assert(list2.length == 1);
复制代码

b. Dart 2.3 还可使用 if 和 for 来构建列表async

// 使用 if 建立3个或4个元素的列表
var nav = [
 'Home',
 'Furniture',
 'Plants',
 if (promoActive) 'Outlet'
];

// 使用 for 来建立列表
var listOfInts = [1, 2, 3];
var listOfStrings = [
 '#0',
 for (var i in listOfInts) '#$i'
];
assert(listOfStrings[1] == '#1');
复制代码

sets

Dart中的 Set 存放的是一组无序的惟一的元素,在Dart2.2 Set 引入 literals

// 定了一个 Set,推断为 Set<String>,若是添加其余类型将报错
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};

// 建立空 Set
var names = <String>{}; // Set<String>
// Set<String> names = {}; // Set<String>
// var names = {}; // Map<dynamic, dynamic>
复制代码

敲黑板

Dart 2.3 增长操做符 ... 和 ...? ,提供一种将多个元素插入 Set 的简便方法

maps

// 如下都能定义一个图
var maps = {
  // 键 值
  'a' : '123456'
};
Map maps = Map();
maps[a] = '123456';
复制代码

敲黑板

Dart 2.3 增长操做符 ... 和 ...? ,提供一种将多个元素插入 Map 的简便方法

Runes Symbols

感受不多用 就不看了...

3、函数

函数示例

// 声明返回类型 bool
bool isNoble(int atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}

// 能够不声明类型
isNoble(atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}

// 仅有一个表达式能够这样写
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
复制代码

顶层函数 main()

每一个应用程序都必须具备顶级main()函数,该函数用做应用程序的入口点。 main()函数返回void,并为参数提供可选的List 参数。

void main() {
  querySelector('#sample_text_id')
    ..text = 'Click me!'
    ..onClick.listen(reverseText);
}
复制代码

敲黑板 代码中的..语法称为级联。使用级联,能够对单个对象的成员执行多个操做。

可选参数

函数可选参数能够是可选命名参数,也能够是可选位置参数,但不能2者都有

  • 可选命名参数
// 函数的时候,使用{param1, param2, ...}来声明有命名的参数

// 定义
enableFlags({bool bold, bool hidden}) {
     // ...
}

// 调用
enableFlags(hidden : true);

// 命名参数虽然是可选的,咱们依然能够经过 @required 注解要求必传
const Scrollbar({Key key, @required Widget child})
复制代码
  • 可选位置参数
// 把函数的参数放在[]以内,能够把它们标记为可选位置参数

// 定义
String say(String from, String msg, [String device]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}

// 调用
say('Bob', 'Howdy', 'smoke signal');

复制代码

敲黑板

  1. 函数不能同时拥有可选命名参数和可选位置参数
  2. 可选命名参数和可选位置参数可使用 = 设置默认值
  3. 函数能够做为参数传递,也可定义为一个变量
  4. 函数中亦可嵌套定义函数,也可使用匿名函数
  5. 函数直接定义在文件中(顶级函数),也能够定义在类中
  6. 全部的函数都有返回值。若是没有定义返回值,那么至关于隐式添加语句 return null
  7. 可选命名参数和可选位置参数,区别在于调用的时候需不须要加上参数名

4、操做符

Dart 中拥有其余语言常见操做符

这里说几个不同的:

  1. Dart 中 ?? 、??= 属于操做符,如: A ?? "a" 表示 A 为空将返回a。A ??= "a" 表示 A 为空,将给 A 赋值 a
  2. .. 操做符,对单个对象的成员执行多个操做
  3. ... 、...? 操做符,提供一种将多个元素插入简便操做
  4. ?. 操做符,可空调用,避免异常

5、流程控制

可使用如下任何一种方式来控制你的Dart代码流:

  • if 和 else (能够用三目运算符 ?: 替代)
  • for 循环
  • while 和 do-while 循环
  • break 和 continue
  • switch 和 case
  • assert 断言(布尔条件值为false,使用assert语句来中断正常执行的代码)

7、异常

dart 使用经典的try-catch处理异常,使用关键字throw抛出一个异常

// 抛异常
throw new IntegerDivisionByZeroException("分母不能为0");
// 也能够抛出任意对象
throw 'Out of llamas!';

//处理异常
try {
      divide(10, 0);
} on IntegerDivisionByZeroException {
  // 具体类型用 on
} catch (e) {
  // 非具体类型或要使用异常对象
} finally {
    //...
}
复制代码

8、类

Dart 是一种面向对象语言,包含类和基于 mixin 的继承两部分。每一个对象是一个类的实例,而且 Object 是全部类的父类。基于 mixin 的继承指的是每一个类(除了 Object )都只有一个父类,类体还能够在多个类继承中被重用。

构造函数

若是类没有声明构造函数,将默认无参构造函数。子类不会继承父类构造函数,若子类没有声明构造函数,将也仅默认无参构造函数

class Person {
  String name;
  int age;
  
  //默认构造方法,赋值给name和tag
  Person(this.name, this.age);

  //命名构造函数,返回一个空的Person
  Person.empty();
  
  //命名构造函数,返回设置了name的Person
  Person.forName(this.name);
  
}

// 常量构造函数 全部实例变量须要时 final 
// 常量构造函数产生的对象永远不会改变
class ImmutablePoint {
  static final ImmutablePoint origin =
      const ImmutablePoint(0, 0);

  final num x, y;

  const ImmutablePoint(this.x, this.y);
}

// 工厂构造函数
class Logger {
  final String name;
  bool mute = false;

  // _cache 是个私有的 Map,仅仅由于标注了 _
  static final Map<String, Logger> _cache =
      <String, Logger>{};

  factory Logger(String name) {
    return _cache.putIfAbsent(
        name, () => Logger._internal(name));
  }

  Logger._internal(this.name);

  void log(String msg) {
    if (!mute) print(msg);
  }
}
复制代码

调用无参构造函数顺序:

  1. 初始化列表
  2. 父类无参构造函数
  3. 本类无参构造函数
class Person {
  String firstName;

  Person.fromJson(Map data) {
    print('in Person');
  }
}

class Employee extends Person {
  // Person 没有默认无参构造函数;
  // 必须调用 super.fromJson(data).
  Employee.fromJson(Map data) : super.fromJson(data) {
    print('in Employee');
  }
}
复制代码

初始化列表

class Point {
  num x;
  num y;

  Point(this.x, this.y);

  // 初始化列表在构造函数运行前设置实例变量。
  Point.fromJson(Map jsonMap)
      : x = jsonMap['x'],
        y = jsonMap['y'] {
    print('In Point.fromJson(): ($x, $y)');
  }
}
复制代码
  • 实例变量

全部实例变量都生成一个隐式getter方法。非 final 实例变量也会生成隐式setter方法。

class Point {
  num x; // 定义实例变量x 初始化值 null
  num y; // 定义实例变量y 初始化值 null
  num z = 0; // 定义实例变量z 初始化值 0
  
  // 自定义get set
  num get x => y + z;
  set x(num value) => x = value;
}
复制代码

隐式接口

每一个类都隐式定义一个接口,该接口包含该类的全部实例成员及其实现的任何接口。若是要在不继承B实现的状况下建立支持B类API的A类,则A类应实现B接口。

// 一个 person ,包含 greet() 的隐式接口。
class Person {
  // 在这个接口中
  final _name;

  // 不在接口中,由于这是个构造函数。
  Person(this._name);

  // 在这个接口中。
  String greet(who) => 'Hello, $who. I am $_name.';
}

// Person 接口的一个实现。
class Imposter implements Person {
  // 咱们不得不定义它,但不用它。
  final _name = "";

  String greet(who) => 'Hi $who. Do you know who I am?';
}
复制代码

覆盖操做符

class Vector {
  final int x, y;

  Vector(this.x, this.y);

  Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
  Vector operator -(Vector v) => Vector(x - v.x, y - v.y);

}

void main() {
  final v = Vector(2, 3);
  final w = Vector(2, 2);

  assert(v + w == Vector(4, 5));
  assert(v - w == Vector(0, 1));
}
复制代码

noSuchMethod()

这个很nice,做用是在代码尝试使用不存在的方法或实例变量时检测或作出反应,您能够覆盖noSuchMethod()

class A {
  // 复写这个方法,使用不存在的成员将不会收到NoSuchMethodError
  @override
  void noSuchMethod(Invocation invocation) {
    print('You tried to use a non-existent member: ' +
        '${invocation.memberName}');
  }
}
复制代码

枚举

在枚举中每一个值都有一个 index getter 方法,它返回一个在枚举声明中从 0 开始的位置。

enum Color {
  red,
  green,
  blue
}

assert(Color.red.index == 0);
assert(Color.green.index == 1);
assert(Color.blue.index == 2);

//要获取枚举中全部值的列表
List<Color> colors = Color.values;
assert(colors[2] == Color.blue);
复制代码

Mixins

Dart 2.1中引入了对mixin关键字的支持,早期版本中的代码一般使用抽象类。

Mixins是一种在多个类层次结构中重用类代码的方法。使用mixin,则使用with关键字后跟一个或多个mixin名称。

class Musician extends Performer with Musical {
  // ···
}

class Maestro extends Person with Musical, Aggressive, Demented {
  Maestro(String maestroName) {
    name = maestroName;
    canConduct = true;
  }
}
复制代码

要实现mixin,请建立一个扩展Object的类,而且不声明构造函数。除非您但愿mixin可用做常规类,不然请使用mixin关键字而不是class。例如:

mixin Musical {
  bool canPlayPiano = false;
  bool canCompose = false;
  bool canConduct = false;

  void entertainMe() {
    if (canPlayPiano) {
      print('Playing piano');
    } else if (canConduct) {
      print('Waving hands');
    } else {
      print('Humming to self');
    }
  }
}
复制代码

要指定只有某些类型可使用mixin - 例如,可使用on来指定所需的超类,使你的mixin能够调用它没有定义的方法:

mixin MusicalPerformer on Musician {
  // ···
}
复制代码

9、异步支持

Futures

当你须要使用 Future 的结果时,你有两个选择。

  1. 使用 async 和 await
  2. 使用 Future API

使用async和await的代码是异步的,但它看起来很像同步代码。要使用await,代码必须位于异步函数中,标记为async的函数。如:

Future checkVersion() async {
  var version = await lookUpVersion();
  // Do something with version
}
复制代码

在await表达式中,表达式的值一般是Future;若是不是,那么该值将自动包装在Future中。await表达式使执行暂停,直到该对象可用。

使用try,catch,最后在使用await的代码中处理错误和清理:

try {
  version = await lookUpVersion();
} catch (e) {
  // React to inability to look up the version
}
复制代码

定义异步函数,使用 async 包裹函数体

Future<String> lookUpVersion() async => '1.0.0';

Future<String> lookUpVersion() async {
    //... 
}
复制代码

Streams

当您须要从Stream获取值时,您有两个选择:

  1. 使用async和异步for循环(等待)。
  2. 使用Stream API
await for (varOrType identifier in expression) {
  // Executes each time the stream emits a value.
}
复制代码

表达式 的值必须有Stream 类型(流类型)。执行过程以下:

  1. 在 stream 发出一个值以前等待
  2. 执行 for 循环的主体,把变量设置为发出的值。
  3. 重复 1 和 2,直到 Stream 关闭

若是要中止监听 stream ,你可使用 break 或者 return 语句,跳出循环并取消来自 stream 的订阅 。

10、库和可见性

  • 可见性

可见性经过 _ 控制,前面已经说过了

  • 使用库

导入的惟一必需参数是指定库的URI。

//对于内置库
import 'dart:html';

//对于其余库,你可使用文件系统路径或package:scheme
import 'dart:io';
import 'package:test/test.dart';
复制代码
  • 指定库前缀

若是导入两个具备冲突标识符的库,则能够为一个或两个库指定前缀。

import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;

// 使用lib1里的元素
var element1 = Element(); 

 // 使用lib2里的元素
var element2 = lib2.Element();    
复制代码
  • 仅导入库的一部分

若是只想使用库的一部分,则能够有选择地导入库。

// 仅导入 foo.
import 'package:lib1/lib1.dart' show foo;

// 导入全部 除了 foo.
import 'package:lib2/lib2.dart' hide foo;
复制代码
  • 延迟加载库

只有dart2js支持延迟加载。Flutter,Dart VM和dartdevc不支持延迟加载。 因此不看了

相关文章
相关标签/搜索