Flutter笔记--Dart基础语法

2020-02-24  本文已影响0人  ywy_袁滚滚

Dart中一切皆对象

Dart内置类型

Numbers

Numbers类型包含两种:
int :int类型不超过64位,根据平台的不同,取值范围不同。在Dart虚拟机中int取值范围为-2632 63,编译成JavaScript的Dart使用 JavaScript numbers,允许从-2 53253 - 1的值
double :64位(双精度)浮点数,由IEEE 754标准指定

  //int 和 double 都是num的子类型
  num n = 10;
  num n1 = 20.0;
  
  int i = n;
  double d = n1;

  print(i.runtimeType); //int
  print(d.runtimeType); //double
  print(n.runtimeType); //int
  print(n1.runtimeType); //double

 //在Dart2.1,必要的话,整型会自动转换为双精度
  double z = 1;  //相当于double z = 1.0, 在Dart2.1之前这种写法是会报错的
String

字符串创建方式:‘单引号创建’“双引号创建”'''三个单引号(有格式的)'''"""三个双引号(有格式的)"""以r为前缀的原始字符串

//单引号和双引号比较常用
String s = 'single quotes';
String d = "double quotes";

//三个单引号和三个双引号是一样的
String t = '''three single quotes''';
String t1 = """three double quotes""";

//三个单、双引号字符串一般用于创建多行字符串,即
  String t2= '''$t
         can be styled virtually
 any way you want ''';

//输出结果即包含输入的样式
  print(t2);
  /**

      three single quotes
      can be styled virtually
      any way you want
   */
//在单双引号或三单引号以及三双引号中$、\n等特殊字符还是会特殊处理的,而对于以r为前缀的原始字符串来说,任何字符都不会得到区别对待
  int i = 10;
  var s = r'In a raw string,$i not even \n gets special treatment.';

  var s1 = 'In a raw string, $i not even \n gets special treatment.';
  print(s);
  print(s1);
    /*
      In a raw string,$i not even \n gets special treatment.
      In a raw string, 10 not even
      gets special treatment.
     */

//其中 ${表达式} 可以获取到该表达式的值,另外该表达式本身是一个变量时可省略{}

另外再说一下dart中字符串的拼接,除了+操作符拼接还可直接排放到一起

 String jointStr1 = 'str1'+'str2'+'str3';
 String jointStr2 = 'str1''str2''str3';
 print('$jointStr1 \n$jointStr2');
  /*
  str1str2str3 
  str1str2str3
  */ 
Boolean

Dart使用bool表示布尔值,只有两个对象具有bool类型,truefalse,都是编译时常量

 String jointStr1 = 'str1'+'str2'+'str3';
 String jointStr2 = 'str1''str2''str3';
 bool a = jointStr1 == jointStr2;
  if (a) {
    print('==操作符可用于判断两个对象是否相等,当两个字符串包含的字符一致时,这两个字符串是相等的');
  }

Lists

在Dart中,Array也是List,所以统称为Lists(列表).与其它编程语言类似,列表使用基于0的索引,其中0是第一个元素和列表的索引。length - 1是最后一个元素的索引

 //声明一个List
  List list = [1,2,3];

  //获取list中的元素
  print(list[0]); //1
  print(list.first);//1
  print(list.length); //3
  print(list[list.length-1]); //3
  print(list.last); //3

  //添加和删除元素
  list.add(4);
  print(list); //[1, 2, 3, 4]
  list.remove(1);
  print(list); //[2, 3, 4]
  list.removeAt(0);
  print(list); //[3, 4]
  list.insert(0, 1);
  print(list); //[1, 3, 4]
  list.insert(1, 2);
  print(list); //[1, 2, 3, 4]

  //需要注意list的insert(int index,E element)方法中的index取值范围为0..${list.length}
  print(list.length); //4
  list.insert(4, 5);
  print(list); //[1, 2, 3, 4, 5]
  // list.insert(6, 6); // throw RangeError: Invalid value: Not in range 0..5, inclusive: 6

Maps

(Map)映射,是一个将键和值(keys-values)关联起来的对象。key和value都可以是任何类型的对象,在一个map中,每个key只能出现一次,但是多个key,可以对应同样的value

//定义一个Map
Map<int,String> map = {
  //key : value
     1  : 'a',
     2  : 'b',
     3  : 'c',
};

//添加一个新的key:value
map[4] = 'b';

//根据key获取value
print('${map[1]}'); //a
  
//移除key
map.remove(4);
print('${map[4]}'); //null  ,当key不存在时,返回null

Runes

在Dart中,符文是字符串的UTF-32编码点。

Unicode为世界上所有的书写系统中使用的每个字母、数字和符号定义一个惟一的数字值。由于Dart字符串是UTF-16代码单元的序列,因此在字符串中表示32位Unicode值需要特殊的语法。

表达Unicode编码点的常用方法是\uXXXX,其中XXXX是一个4位十六进制值。例如,心字符(♥)表示为\ u2665。若要指定多于或少于4位十六进制数字,请将值放在大括号中。

String类有几个属性可以用来提取rune信息。codeUnitAt和codeUnit属性返回16位代码单元。使用runes属性获取字符串的runes。

下图来自官网 runes演示结果.png

Dart变量声明

var

var可以接收任意类型的变量(类似于java中的Object),Dart可以通过类型推导判断该变量的类型。但是需要注意的是,当使用var声明一个变量的时候直接给它赋值,该变量的类型便会确定下来,无法再改变其类型

  var variable;
  variable = 'Dart String';
  print(variable.runtimeType); //String
  variable = 10;
  print(variable.runtimeType); //int
  variable = true;
  print(variable.runtimeType); //bool
  
  var variable2 = 'Dart String 2'; //直接赋值,此时Dart类型推导认为variable2类型为String
  variable2 = 10; //编译报错:A value of type 'int' can't be assigned to a variable of type 'String'.
dynamic和Object

对于使用dynamic声明的变量,Dart也会进行类型推导从而可以动态的改变该变量的类型,而由于Object是所有类型的基类,所以任何类型都可以赋值给Object类型的变量。两者与var的不同在于即使在声明时赋值,也可以动态改变其类型

  dynamic variable = 'Dart String';
  print(variable.runtimeType); //String
  variable = 10;
  print(variable.runtimeType); //int
  variable = true;
  print(variable.runtimeType); //bool

  Object variable2 = 'Dart String';
  print(variable2.runtimeType); //String
  variable2 = 10;
  print(variable2.runtimeType); //int
  variable2 = true;
  print(variable2.runtimeType); //bool

前面List的声明方式,是可以添加任何类型的对象的

 //由于未给List指定类型,所以实际是下面的声明方式为List<dynamic> list = [1,2,3,4];
  List list = [1,2,3,4];
  list.add(null);
  list.add("str");
  list.add(true);
  print(list); //[1, 2, 3, 4, 5, null, str, true]

  var element;
  for(element in list){
    print('元素$element 的类型为${element.runtimeType}');
  }
  /*
元素1 的类型为int
元素2 的类型为int
元素3 的类型为int
元素4 的类型为int
元素5 的类型为int
元素null 的类型为Null
元素str 的类型为String
元素true 的类型为bool
*/

var list2 = [1,2,3]; //此时list2的类型实际上为List<int>
list2.add(true);//编译报错:The argument type 'bool' can't be assigned to the parameter type 'int'.
Final和const

对于一个只需要初始化一次,就无需再次改变的变量,请使用finalconstfinalconst不是一种类型,也不像var那样可以动态改变类型。final声明的变量只能赋值一次,在第一次访问的时候被初始化。而const声明的变量是编译时常量

final f = 'Dart String';
f = "d"; //编译报错:'f', a final variable, can only be set once

const c = 'Dart String';
c = 'd'; //编译报错:Constant variables can't be assigned a value(常量变量无法赋值)

final f1; //编译报错:The final variable 'f1' must be initialized.
const c1; //编译报错:The const variable 'c1' must be initialized.

const关键字不仅仅用于声明常量变量。它还可以用来创建常量值,以及声明创建常量值的构造函数。任何变量都可以有一个常量值

dynamic d = const [1,2,3]; //将常量值赋值给变量
//你可以改变一个非final,非const变量的值,即使它曾经有一个const值
d = 'Dart String'; //对于d来说它依旧是dynamic类型的,依旧可以动态改变类型

final f = const [1,2,3]; //将常量值赋值给final声明的变量
Default value

未初始化的变量的初始值为null。即使是int类型的变量未初始化时也是null,因为Dart中,所有东西都是对象

int i;
print(i); //null
bool b;
print(b);//null

Dart函数

还是那句话:Dart中,所有东西都是对象,所以函数也不例外。函数也是一个对象,并且有一个类型Function。这意味着函数可以被赋值给变量,也可以作为参数传递给其他函数

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

  //私有的
  int _mod(int a, int b) {
    return a % b;
  }
  var s = 10; //前面已经说过,对于这种写法,此时s的类型实际上已经确定为int
  s = getVersionName(); // 对于省略了返回类型的函数而言,默认的类型为dynamic,所以编译期并不会报错,运行时报错
  s = "sss";  //这种写法直接编译报错:A value of type 'String' can't be assigned to a variable of type 'int'.

 getVersionName(){
  return "v1.0";
 }
函数省略返回类型.png 函数省略返回类型测试结果.png
getVersionName() => "v1.0";
//a为必须参数,b,c为命名参数
String append(String a, {String b, String c}) {
  return "$a$b$c";
}

//@required表明命名参数a是必须的
String append1({@required String a,String b, String c}){
  return "$a$b$c";
}



main() {
   print(append("a")); //anullnull

   print(append(b: "b",c: "c"));//编译报错:1 required argument(s) expected, but 0 found.

   print(append("a",b: "b")); //abnull

   print(append("a",c: "c")); //anullc

  print(append("a", b: "b", c: "c")); //abc
}
String append2(String a, [String b, String c]) {
  return "$a$b$c";
}

main() {
  print(append2("a")); //anullnull
  print(append2("a","b")); //abnull
  print(append2("a","b","c"));//abc
}
String append3(String a, {String b = "b", String c}) {
  return "$a$b$c";
}

main() {
   print(append3("a")); //abnull
}
void printElement(int element) {
  print(element);
}

var list = [1, 2, 3];

list.forEach(printElement); //1 2 3

//forEach方法
/**
  * Applies the function [f] to each element of this collection in iteration
  * order.
  */
void forEach(void f(E element)) {
   for (E element in this) f(element);
}

//对于上面的函数作为参数传递中的例子而言,创建了一个命名函数printElement传入forEach方法,相对来说是比较冗余的做法

//正常的写法是创建一个匿名函数
 var list = [1, 2, 3];
 list.forEach((element) {
    print('$element');
  });

常用操作符

  var a = 5/2;
  var b = 6/2;
  var c = 5~/2;
  var d = 6~/2;

  print("$a:type is ${a.runtimeType}"); //2.5:type is double
  print("$b:type is ${b.runtimeType}"); //3.0:type is double
  print("$c:type is ${c.runtimeType}"); //2:type is int
  print("$d:type is ${d.runtimeType}"); //3:type is int
import 'dart:math' as mm;  //as指定库前缀

main(){
var dog = Dog();

  if (dog is Animals) {
    print('${dog.name} is animals'); //dog is animals
  }

  var apple = Apple();
  if (apple is! Animals) {
    print('apple isn\'t animals');     //apple isn't animals
  }

  sayHi(dog); // Hi,i'm dog

 print(mm.min(1, 2)); //1
}

class Animals {
  var name = "animals";

  void sayHi() {
    print('Hi,i\'m $name');
  }
}

class Dog extends Animals {
  @override
  String get name => "dog";
}

class Apple {}

//需要注意的是当传入的t不是Animals类型或不是Animals的子类,报错。此处仅作演示
void sayHi<T>(T t) {
  (t as Animals).sayHi();
}
var human = Human();
human
    ..name = 'human'
    ..sex = 'male'
    ..age = 25;
var result = human.age>20 ? "yes" : "no"; //yes
var result1 =  human.sex == 'female' ? "yes" : "no"; //no
var result2 = human.girlfriend?? "get null"; //get null
var result3 = human.name ?? "get null"; //human


var human1;
var result4 = human1?.name;   // null

class Human {
  var name = 'human';
  var sex;
  var age;
  var girlfriend;
}

控制流程

var sex = "male";
  if (sex == "male") {
    print('he is a man');
  } else if (sex == "female") {
    print('she is a woman');
  } else {
    print('unknow');
  }

  var type = "A";
  //需要注意的是case中的类型必需与type的类型一致
  switch (type) {
    case "A":
      print('type is A');
      break;
    case "B":
      print('type is B');
      break;
    case "C":
      print('type is C');
      break;
    default:
      break;
  }
 var array = [1, 2, 3, 4];
  for (int i = 0; i < array.length; i++) {
    print(element);
  }

  for (var i in array) {
    print(i);
  }

  array.forEach((element) {
    print(element);
  });

  //还可以简写如下
  array.forEach((element) => print(element));
  var sum = 0;
  while (sum < 10) {
    sum++;
  }
  print(sum); //10
var array = [1, 2, 3, 4];
//捕获所有异常
  try {
    print(array[10]);
  } catch (e) {
    print(e);
  }finally{
    print('finally block');
  }
//RangeError (index): Invalid value: Not in range 0..3, inclusive: 10
//finally block

//捕获指定异常
  try {
    print(array[4]);
  } on RangeError  {
    print(RangeError);
  }finally{
    print('finally block');
  }
//RangeError
//finally block


class Person {
  String name;
  int _age;

  Person(String name, int age) {
    this.name = name;
    this._age = age;
  }

}
class Person {
  String name;
  int _age;

  Person(this.name, this._age); //与上面的写法等价
}
class Person {
  String name;
  int _age;

  Person(this.name, this._age);

  Person.fromJson(Map data) {
    this.name = data["name"];
    this._age = data["age"];
  }
}

main(){
  Person p = Person.fromJson({"name": "aaa", "age": 10});
  print("p.name:${p.name},p._age:${p._age}"); //p.name:aaa,p._age:10
}
class Person {
  String name;

  int _age;

  Person(this.name, this._age);

  //命名构造函数
  Person.name(this.name);

//命名构造方法重定向到同名构造方法,实际上调用了Person(this.name, this._age);
  Person.age(int age) :this("", age);
}
class Person {
  final String idCard;
  static Map<String, Person> _cache;

  factory Person(String idCard) {
    if (_cache == null) {
      _cache = {};
    }
    if (_cache.containsKey(idCard)) {
      return _cache[idCard];    //加了factory之后需要明确的返回一个对象
    } else {
      final Person p = new Person._instance(idCard);
      _cache[idCard] = p;  
      return p;   //加了factory之后需要明确的返回一个对象
    }
  }

  //私有的命名构造函数
  Person._instance(this.idCard);
}

main(){
  Person p = new Person("4416**199*1201****");
  Person p1 = new Person("4416**199*1201****");
  Person p2 = new Person("aa");
  print(p == p1); //true
  print(p == p2); //false
}
class PI {
  final num value;

  //const 修饰,表明是常量构造方法
  const PI(this.value);

  //编译时常量对象,需要使用const来创建对象
  static final PI pi = const PI(3.14);
}

main() {
  print(PI.pi.value);
}
class Animal {
  String name;

  Animal(this.name);

  void eat() {
    print("$name eat");
  }
}

class Dog extends Animal {
  
  Dog(String name) : super(name);

  @override
  void eat() {
    super.eat();
  }
}
class A{
  void a(){
    print('a');
  }
}

class B{
  void b(){
    print('b');
  }
}

class C{
  void c(){
    print('c');
  }
}

class D extends A with B,C{}

main(){
  D d = new D();
  d.a();  //a
  d.b(); //b
  d.c(); //c
}
class D with A, B, C {}
class A {
  void action() {
    print('a doSomething');
  }
}

class B {
  void action() {
    print('b doSomething');
  }
}

class C {
  void action() {
    print('c doSomething');
  }
}

class D with A, B, C {}
class E with A, C, B {}
class F with B, C, A {}

main(){
  D d = new D();
  d.action(); //c doSomething
  
  E e = new E();
  e.action(); //b doSomething

  F f = new F();
  f.action(); //a doSomething
}

异步支持

Dart库中包含许多返回Future或Stream对象的函数。 这些函数是异步的:它们在设置一个可能非常耗时的操作(例如I / O)后返回,而不需要等待该操作完成。

abstract class FutureOr<T> {
  // Private generative constructor, so that it is not subclassable, mixable, or
  // instantiable.
  FutureOr._() {
    throw new UnsupportedError("FutureOr can't be instantiated");
  }
}

[Future]用来表示将来某个时候可能出现的潜在值或错误。一旦值或错误可用,[Future]的接收者可以注册回调来处理它。

我们可以简单的认为Future是一个任务,该任务会返回我们需要的结果。这个任务的执行可能是耗时的。而任务的执行过程也可能出现错误。一个Future对应一个结果,要么成功,要么失败。一般使用方法如下

Future<T> future = getFuture();
future.then((value) => handleValue(value))
         .catchError((error) => handleError(error));
Future.then
/**
 * Register callbacks to be called when this future completes.
 */
  Future<R> then<R>(FutureOr<R> onValue(T value), {Function onError});

当任务完成时会回调,能够获取任务执行的返回值并进行处理

  //接收结果并处理,假设 getFuture()是一个网络请求等延时操作

  Future<int> future = getFuture();
  future.then((value) => print(value)); //1

  Future<int> getFuture() {
    return Future.value(1);
  }
//也能直接处理异常

 Future<int> future = getFuture();
  future.then((value) => print(value),onError:(e){print(e);});   //-1

Future<int> getFuture() {
  return Future.error(-1); 
}
Future.catchError
 /**
   * This is the asynchronous equivalent of a "catch" block.
   *
   * If `test` returns false, the exception is not handled by this `catchError`,
   * and the returned future completes with the same error and stack trace as this future.
   *
   * If `test` returns `true`,[onError] is called with the error and possibly stack trace,
   *  and the returned future is completed with the result of this call in exactly the same way as for [then]'s `onError`.
   *  
   * If `test` is omitted, it defaults to a function that always returns true.
   *
   * If the first `catchError` (or `then`) call happens after this future
   * has completed with an error then the error is reported as unhandled error.
   */

 Future<T> catchError(Function onError, {bool test(Object error)});

相当于一个catch块,捕获异常,区别多了个可选参数test来操作是否要处理该异常。如果可选参数test方法返回false,则该catchError方法不处理异常,直接抛出去让别人处理,如果返回true,就会由catchErroronError函数处理,并且使用与thenonError完全相同的方法来完成返回的future。test默认返回true。需要注意的是,如果在调用catchError之前错误就已经发生了,该错误会被当做未处理异常而不会被catchError捕获

  Future<int> future = getFuture();
  future.then((value) => print(value))
        .catchError((e){print(e);});  //-1

  Future<int> getFuture() {
    return Future.error(-1);
  }
  Future<int> future = getFuture();  //直接报错抛异常
  future.then((value) => print(value)).catchError((e) {
    print(e);
  });

Future<int> getFuture() {
  throw Exception("error");
//  return Future.error(-1);
}
Future.delayed
 /**
   * Creates a future that runs its computation after a delay.
   *
   * The [computation] will be executed after the given [duration] has passed,
   * and the future is completed with the result of the computation.
   */
 factory Future.delayed(Duration duration, [FutureOr<T> computation()])

延时执行任务

  Future.delayed(new Duration(seconds: 2),(){
    print('延时2s执行');});   //两秒后输出
}
 Future.delayed(new Duration(seconds: 2)).then((_){
    print('延时2s执行');
  });
//在这由于Exception延时2s才抛出,所以会被then的'onError'捕获

Future.delayed(new Duration(seconds: 2), () {
    throw Exception("error");
  }).then((_) {
    print('成功执行');
  }, onError: (e) {
    print('onError 错误');
  }).catchError((e1) {
    print('catchError 错误');
  });
Future.wait
/**
   * Waits for multiple futures to complete and collects their results.
   *
   * Returns a future which will complete once all the provided futures have completed,
   * either with their results, or with an error if any of the provided futures fail.
   *
   * The value of the returned future will be a list of all the values that
   * were produced in the order that the futures are provided by iterating
   * [futures].
   *
   * If any future completes with an error,
   * then the returned future completes with that error.
   *
   *
   * If `eagerError` is true, the returned future completes with an error immediately on the first error from one of the futures.
   * Otherwise all futures must complete before the returned future is completed (still with the first error; the remaining errors are silently dropped).
   * 
   * In the case of an error, [cleanUp] (if provided), is invoked on any non-null result of successful futures. This makes it possible to `cleanUp` resources that would otherwise be lost (since the returned future does not provide access to these values). The [cleanUp] function is unused if there is no error.
   */
 static Future<List<T>> wait<T>(Iterable<Future<T>> futures,{bool eagerError: false, void cleanUp(T successValue)})

如果有多个延时任务,想要等它们都完成才执行别的任务,可以用Future.wait实现。所有Future任务会按照提供的顺序以集合的形式将任务结果返回。如果其中的部分任务出错了会怎么处理呢?eagerErrortrue,当出现第一个错误的时就会立即返回一个错误,如果为false,所有的任务都会被执行,任务都完成后依旧返回第一个错误,其它的错误会被丢弃。eagerError默认为false。任务有出错,wait会返回一个错误,那么对于其中成功的任务的返回值,都可以由cleanUp接收,在里面可以做额外的处理,比如资源的释放等。

 Future.wait([
    Future.delayed(new Duration(seconds: 1), () {
      print('task one');
      return Future.value(1);
    }),
    Future.delayed(new Duration(seconds: 3), () {
      print('task two');
      return Future.value(2);
    }),
    Future.delayed(new Duration(seconds: 5), () {
      print('task three');
      return Future.value(3);
    })
  ]).then((listValue) {
    listValue.forEach((element) {
      print(element);
    });
  });

结果如下:

future.wait.png
 Future.wait([
    Future.delayed(new Duration(seconds: 1), () {
      print('task one');
      return Future.value(1);
    }),
    Future.delayed(new Duration(seconds: 3), () {
      print('task two');
      return Future.error(-2);
    }),
    Future.delayed(new Duration(seconds: 5), () {
      print('task three');
      return Future.value(3);
    }),
    Future.delayed(new Duration(seconds: 7), () {
     print('task four');
      return Future.error(-4);
    })
  ],eagerError: false,cleanUp: (successValue){
    print('接收到$successValue,回收资源');
  }).then((listValue) {
    listValue.forEach((element) {
      print(element);
    });
  }).catchError((e)=> print("捕获到错误:$e"));

结果如下,等所有任务执行完成,只返回第一个错误

clearUp处理.png

再来看下eagerErrortrue的情况

 Future.wait([
    Future.delayed(new Duration(seconds: 1), () {
      print('task one');
      return Future.value(1);
    }),
    Future.delayed(new Duration(seconds: 3), () {
      print('task two');
      return Future.error(-2);
    }),
    Future.delayed(new Duration(seconds: 5), () {
      print('task three');
      return Future.value(3);
    }),
    Future.delayed(new Duration(seconds: 7), () {
      print('task four');
      return Future.error(-4);
    })
  ],eagerError: true,cleanUp: (successValue){
    print('接收到$successValue,回收资源');
  }).then((listValue) {
    listValue.forEach((element) {
      print(element);
    });
  }).catchError((e)=> print("捕获到错误:$e"));

结果如下,可以看到当出现错误时会立即被捕获到

eagerError为true.png

async和await

//定义任务

Future<File> getImageFile(String url) {
  return Future.delayed(new Duration(seconds: 2), () {
    print('下载图片');
    return new File(url);
  });
}


Future<File> handleFile(File file) {
  return Future.delayed(new Duration(seconds: 2), () {
    print('处理图片');
    return file;
  });
}

Future<bool> saveFile(File file) {
  return Future.delayed(new Duration(seconds: 2), () {
    print('保存图片图片');
    return true;
  });
}

如果不熟悉Future,可能会出现嵌套调用

  getImageFile("***********").then((file) {
    handleFile(file).then((file2) {
      saveFile(file);
    });
  }).catchError((e) {
    print(e);
  });

实际上Future本身支持链式调用,可以让结构看起来更加清晰

 getImageFile("***********").then((file) {
    return handleFile(file);
  }).then((file2) {
    return saveFile(file2);
  }).catchError((e) {
    print(e);
  });

不管怎么链式调用,实际上还是会有多一层回调,而使用asyncawait,则可以像写同步代码一样处理异步操作

action() async {
  try {
    File file = await getImageFile("***********");
    File file2 = await handleFile(file);
    bool result = await saveFile(file2);
  } catch (e) {
    //
  } finally {
    //
  }
}

结果如下

20200117151319.png
 //创建控制器
  StreamController _controller = StreamController();

  //获取控制器控制流的入口
  StreamSink sink = _controller.sink;

  //获取控制器控制的流
  Stream stream = _controller.stream;

  //监听流,返回订阅对象
  StreamSubscription streamSubscription = stream.listen((onData) {
    print(onData);
  });
  //错误监听
  streamSubscription.onError((e) {
    print(e);
  });
  streamSubscription.onDone((){
    print("done");
  });

  //传递事件
  _controller.add("controller add");
  _controller.add(1);
  sink.add("sink add");
  sink.add(2);
  sink.addError(Exception("error"));

   //暂停
//  streamSubscription.pause();
   //恢复
//  streamSubscription.resume();
  //取消订阅
//  streamSubscription.cancel();
stream使用.png
import 'dart:async';

Future<int> sumStream(Stream<int> stream) async {
  var sum = 0;
  await for (var value in stream) {
    sum += value;
  }
  return sum;
}

//新建一个返回 Stream 的异步函数需要使用 async* 来标记, 使用 yield 或 yield* 来发射数据
Stream<int> countStream(int to) async* {
  for (int i = 1; i <= to; i++) {
    yield i;
  }
}

main() async {
  var stream = countStream(10);
  var sum = await sumStream(stream);
  print(sum); // 55
}

Future<T> get first;
Future<bool> get isEmpty;
Future<T> get last;
Future<int> get length;
Future<T> get single;
Future<bool> any(bool Function(T element) test);
Future<bool> contains(Object needle);
Future<E> drain<E>([E futureValue]);
Future<T> elementAt(int index);
Future<bool> every(bool Function(T element) test);
Future<T> firstWhere(bool Function(T element) test, {T Function() orElse});
Future<S> fold<S>(S initialValue, S Function(S previous, T element) combine);
Future forEach(void Function(T element) action);
Future<String> join([String separator = ""]);
Future<T> lastWhere(bool Function(T element) test, {T Function() orElse});
Future pipe(StreamConsumer<T> streamConsumer);
Future<T> reduce(T Function(T previous, T element) combine);
Future<T> singleWhere(bool Function(T element) test, {T Function() orElse});
Future<List<T>> toList();
Future<Set<T>> toSet();
Stream<R> cast<R>();
Stream<S> expand<S>(Iterable<S> Function(T element) convert);
Stream<S> map<S>(S Function(T event) convert);
Stream<T> skip(int count);
Stream<T> skipWhile(bool Function(T element) test);
Stream<T> take(int count);
Stream<T> takeWhile(bool Function(T element) test);
Stream<T> where(bool Function(T event) test);

参考

Language Tour | Dart

上一篇 下一篇

猜你喜欢

热点阅读