Dart基础系统学习

27次阅读

共计 16989 个字符,预计需要花费 43 分钟才能阅读完成。

目录介绍

  • 01. 变量声明

    • 1.1 var 声明变量
    • 1.2 变量和常量
    • 1.3 dynamic 和 Object
  • 02. 数据类型

    • 2.1 基本数据类型
    • 2.2 String 字符串
    • 2.3 List 数组
    • 2.4 Map 集合
  • 03.Dart 函数和运算符

    • 3.1 Dart 函数介绍
    • 3.2 命名参数
    • 3.3 参数默认值
    • 3.4 void 无返回值
    • 3.5 匿名函数
    • 3.6 运算符介绍
  • 04.Dart 流程控制

    • 4.1 流程控制语句
    • 4.2 if 和 else
    • 4.3 for 循环
    • 4.4 while 循环
    • 4.5 break 和 continue
    • 4.6 switch 和 case
    • 4.7 assert 断言
  • 05.Dart 面向对象

    • 5.1 类简单介绍
    • 5.2 构造函数
    • 5.3 继承类
    • 5.4 重载和重写
    • 5.5 抽象类
    • 5.6 访问权限
    • 5.7 静态方法
    • 5.8 泛型
  • 06.Dart 异步解读

    • 6.1 Future 简单介绍

      • 6.1.1 普通异步案例
      • 6.1.2 耗时异步案例
    • 6.2 async/await 介绍
    • 6.3 看一个案例
  • 07.Dart 异常捕获

    • 7.1 异常处理形式
    • 7.2 抛出异常
    • 7.3 捕获异常
    • 7.4 Finally 讲解
  • 08.Dart 枚举

    • 8.1 枚举使用
    • 8.2 元数据
    • 8.3 自定义注解
  • 09.Dart 字符串

    • 9.1 String 简单介绍
    • 9.2 单双引号互相嵌套
    • 9.3 字符串拼接方式

想换个工作,渴望同行内推我

  • 个人信息

    • 姓名:杨充【26 岁】
    • 邮箱:yangchong211@163.com
    • 微信:13667225184
    • GitHub:https://github.com/yangchong211
    • 博客汇总:https://github.com/yangchong2…
    • 干活集中营:Android 端技术博客和开源项目审核员
    • 目前工作情况:在职状态
    • 技术项目和博客:GitHub 项目 7k 以上 star,follower1.1k 以上,发表博客 100 多篇。
    • 热爱技术:开源项目和博客多次被鸿洋,郭霖,Android 技术周刊,干活集中营等等推荐。
    • 学历:武汉软件工程职业学院,大专学历
    • 工作年限:3 年多
    • 工作地点:北京
  • 关于近期投递简历一点感想

    • 从进入 Android 这个行业以来,前两次几乎都是朋友内推,面试机会相对容易,都是一个 App 一个人做或者两个人做,用户相对来说并不多。这次想着离职,主要是想进入一个较大的平台,大概可以理解为 Android 端有个至少四五人,可以进行技术交流,渴望自己能够在技术上突破,这就像自己平时独自跑步,和跟着一群跑马拉松的人跑步,那种紧张感肯定是不一样的。
    • 近段时间,尝试着向一些较大的公司投递简历,大概在拉钩上投了 15 个左右(不喜欢海投),发现绝大多数简历到不了技术那里,就被人事说学历不够,经验不够,工作不匹配等情况回绝。不过也可以理解,看简历无非就是学历和经验,貌似自己的履历是差了一点。
    • 这大概是第一次在网上发一个主动希望同行内推的介绍,如果你的公司有 Android 方面的招聘,能否内推一下我这个小人物,感谢。

01. 变量声明

1.1 var 声明变量

  • 类似于 kotlin 中的var,它可以接收任何类型的变量,但最大的不同是 Dart 中 var 变量一旦赋值,类型便会确定,则不能再改变其类型,如:

    var t;
    t="yc";
    // 下面代码在 dart 中会报错,因为变量 t 的类型已经确定为 String,// 类型一旦确定后则不能再更改其类型。t=1000;
    • 最大的不同是 Dart 中 var 变量一旦赋值,类型便会确定,则不能再改变其类型。因为 Dart 本身是一个强类型语言,任何变量都是有确定类型的,在 Dart 中,当用 var 声明一个变量后,Dart 在编译时会根据第一次赋值数据的类型来推断其类型,编译结束后其类型就已经被确定。
  • 思考一下,dart 在编译时是如何确定数据的类型呢?

1.2 变量和常量

1.2.1 变量
  • 变量如下所示

    var curPage = 0;
    var title = "潇湘剑雨:小杨逗比";
  • Dart 不需要给变量设置 setter getter 方法,这和 kotlin 等类似。Dart 中所有的基础类型、类等都继承 Object,默认值是 NULL,自带 getter 和 setter,而如果是 final 或者 const 的话,那么它只有一个 getter 方法。
1.2.2 常量
  • const 的值在编译期确定,final 的值要到编译时才确定。

    • Dart 中 final 表示常量

      //final 表示常量
      final title = "潇湘剑雨:小杨逗比";
    • static const 组合代表了静态常量

      //static const 组合代表了静态常量
      static const String complete = "COMPLETE";
  • final 和 const 区别

    • 两者区别在于:const 变量是一个编译时常量,final变量在第一次使用时被初始化。被 final 或者 const 修饰的变量,并且变量类型可以省略。
  • 注意点

    • const 变量同时也是 final 变量,实例变量可以为 final 但不能是 const。
    • 编译错报错,原因 final 变量只能赋值一次!
    // 定义初始化一个变量
    final double number = 13.14;
    number = 520;
    // 调用打印数字方法
    printNumber(number);
1.2.3 注意 +
  • 在 Java 中可以直接通过 + 号将字符串和 int 类型拼接,但是在 Dart 中是不行的。

    // 在 Java 中,下面操作可行
    ToastUtils.showRoundRectToast("二维码扫描"+1000);
    
    // 在 dart 中,下面错误操作,编译不通过,直接会有红色提示
    int yc = 0;
    print("潇湘剑雨" + yc);
    
    // 在 dart 中,下面正确操作
    int yc = 0;
    print("潇湘剑雨" + yc.toString());

1.3 dynamic 和 Object

  • Object 是 dart 所有对象的根基类,也就是说所有类型都是 Object 的子类 (包括 Function 和 Null),所以任何类型的数据都可以赋值给Object 声明的对象.

    • dynamicvar 一样都是关键词, 声明的变量可以赋值任意对象. 而 dynamicObject相同之处在于, 他们声明的变量可以在后期改变赋值类型.
    dynamic t;
    Object x;
    t = "hi world";
    x = 'Hello Object';
    // 下面代码没有问题
    t = 1000;
    x = 1000;
    • dynamicObject 不同的是,dynamic声明的对象编译器会提供所有可能的组合, 而 Object 声明的对象只能使用 Object 的属性与方法, 否则编译器会报错. 如:
 dynamic a;
 Object b;
 main() {
     a = "";
     b = "";
     printLengths();}   

 printLengths() {
     // no warning
     print(a.length);
     // warning:
     // The getter 'length' is not defined for the class 'Object'
     print(b.length);
 }
  • 变量 a 不会报错, 变量 b 编译器会报错

    • dynamic的这个特性与 Objective-C 中的 id 作用很像.
    • dynamic的这个特点使得我们在使用它是需要格外注意, 这很容易引入一个运行时错误.

02. 数据类型

2.1 基本数据类型

  • var 可以定义变量,同时 Dart 属于动态类型语言,支持闭包。

    • Dart 中 number 类型分为 int 和 double,其中 java 中的 long 对应的也是 Dart 中的 int 类型。Dart 中没有 float 类型。
    //int 类型   这里没有 long 类型
    var positionIndex = 0;
    
    //double 类型   这里没有 float 类型
    var time = 1993.03;
    • 这里提个小建议,声明变量的时候,可以选择加上具体类型。添加类型可以更加清晰表达你的意图。
    // 定义初始化一个变量
    double number = 13.14;
  • Dart 下只有 bool 型可以用于 if 等判断,不同于 JS 这种使用方式是不合法的 var g = “null”; if(g){}。

    • 以 bool 代表布尔值,只有两个对象是布尔类型的,那就是 true 和 false 所创建的对象,这两个对象都是编译时常量。
    // 类似 Java 中的布尔类型
    bool mIsLogin = false;
    
    if (!mIsLogin) {
      // 没有登陆
      print('没有登陆');
    } else {
      // 已经登陆
      Navigator.of(context).push(new MaterialPageRoute(builder: (context) {return new CollectPage();
      }));
    }
    • 注意,下面这种情况会报错
    String name ="yc";
    // 报错 因为 name 不是 bool 类型
    if(name){print(name);
    }
    • 可以使用的是先式的检查值。assert 是语言内置的断言的函数,仅在检查模式有效,在开发过程中,除非条件为真,否则会引发异常。(断言失败则程序立刻终止)
    // 检查是否为空字符串
    var fullName = 'doubi';
    assert(fullName.isEmpty);
    
    // 检查是否小于等于 0
    var hitPoints = 0;
    assert(hitPoints <= 0);
    
    // 检查是否为 null.
    var unicorn;
    assert(unicorn == null);
    
    // 检查是否为 NaN.
    var iMeantToDoThis = 0 / 0;
    assert(iMeantToDoThis.isNaN);

2.2 String 字符串

  • Dart 中,switch 支持 String 类型。后面会单独拿出来讲解一下。

    // 字符串
    var title = "潇湘剑雨:小杨逗比";

2.3 List 数组

  • 声明一个 list 非常的简单,可以简单使用方括号 [] 定义 list。下面是 list 的常用操作。

    main(List<String> args) {
      // 或者
      List arr1 = [1,2,3,4];
      var arr2 = [1,2,3,4];
     
      print(list); //Output: [1, 2, 3, 4]
      //Length 长度
      print(list.length);
     
      //Selecting single value 获取单个值
      print(list[1]);    //Outout: 2
     
      //Adding a value 添加值到 list
      list.add(10);
     
      //Removing a single isntance of value 删除单个值
      list.remove(3);
     
      //Remove at a particular position 删除指定位置的值
      list.removeAt(0);
    }
    • 注意:第一个元素索引是 0,最后一个元素是 length-1
  • 如果你想定义一个编译时常量 list,例如,list 的内容是不可改变的,可以使用关键字 const

    var list = const [1,2,3,4];   

2.4 Map 集合

  • 定义 map 也很简单。可以使用花括号 {} 定义 map。

      void test() {
        var map = {
          'key1': 'value1',
          'key2': 'value2',
          'key3': 'value3'
        };
        //Fetching the values 获取值
        print(map['key1']);    //Output: value1
        print(map['test']);    //Output: null
    
        //Add a new value 添加值
        map['key4'] = 'value4';
    
        //Length   获取长度
        print(map.length);
    
        //Check if a key is present 检查是否存在
        var containsKey = map.containsKey('value1');
        print(containsKey);
    
        var entries = map.entries;
        var values = map.values;
      }
    • 打印日志
    2019-06-20 17:22:39.200 4281-4329/com.hwmc.auth I/flutter: value1
    2019-06-20 17:22:39.200 4281-4329/com.hwmc.auth I/flutter: null
    2019-06-20 17:22:39.200 4281-4329/com.hwmc.auth I/flutter: 4
    2019-06-20 17:22:39.200 4281-4329/com.hwmc.auth I/flutter: false
  • 也可以使用 map 构造函数定义 map。

    • 可以发现 map 可以存储多种类型的数据
    var squares = new Map();
    squares["a"] = 1;
    squares["b"] = 2;
    squares["c"] = 3.0;
    squares["d"] = [1,2];
    squares["e"] = "yc 逗比";
    
    print(squares['a']);    
    print(squares['e']);
    • 打印日志
    2019-06-20 17:27:32.841 4281-4329/com.hwmc.auth I/flutter: 1
    2019-06-20 17:27:32.841 4281-4329/com.hwmc.auth I/flutter: yc 逗比

03.Dart 函数和运算符

3.1 Dart 函数介绍

  • dart 中的函数和 JavaScript 中有点类似。你需要定义就是函数的名字、返回值(有返回值或者 void)、参数。

      void test(){var name = fullName('杨充', '逗比');
        print(name);
      }
    
      String fullName(String firstName, String lastName) {return "$firstName $lastName";}

3.2 命名参数

  • dart 有个叫命名参数的东西。当你调用函数的时候,你必须指定参数的名字。要使用命名参数,可以将函数的参数包括在花括号 {} 内。

    • 如果你在调用命名参数的函数时,没有指定参数的名字,则会提示红色报错,无法通过编译。
      void test(){var name = fullName('杨充', '逗比');
        print(name);
      }
    
      String fullName(String firstName, String lastName) {return "$firstName $lastName";}

3.3 参数默认值

  • 你可以给函数的命名参数一个默认值。下面的例子给 lastName 一个默认值。

      void test(){var name = fullName('杨充', '逗比');
        print(name);
      }
    
      fullName(String firstName, String lastName) {return "$firstName $lastName";}

3.4 void 无返回值

  • 大多数都是 void 无返回值的函数,这个跟 java 中类似。没什么好讲的……

3.5 匿名函数

  • 在 dart 中函数比较灵活,例如,你可以将函数当参数传递给另一个函数。

      void test(){out(printOutLoud);
      }
    
      out(void inner(String message)) {inner('Message from inner function');
      }
    
      printOutLoud(String message) {print(message.toUpperCase());
      }
    • 这里定义一个函数名字为 out, 需要一个函数参数。然后我定义一个名为 printOutLoud 的函数,他所做的就是将字符串以大写的形式打印。
    • dart 也有匿名函数,所以上面的例子中不用预定一个函数,而是传递一个匿名函数。
  • 另一个匿名函数的例子。

3.6 运算符介绍

  • 这部分和 java 差不多,可以直接看我 java 部分的博客:运算符

04.Dart 流程控制

4.1 Dart 流程控制

  • 大概有这么多

    • if 和 else
    • for 循环
    • while 循环
    • break 和 continue
    • switch 和 case
    • assert 断言

4.2 if 和 else

  • if-else 和其他语言一样比较简单。

    var number = 57;
    if (number > 100) {print('Large Number');
    } else if (number < 100) {print('Small Number');
    } else {print('Number is 100');
    }
  • 可以用三元运算符代替 if-else

    int age = 60;
    String status = age < 50 ? "年轻人" : "老年人";

4.3 for 循环

  • for 循环和 java 几乎是一样的,代码如下

      void test() {for (int i = 0; i < 10; i++) {print('$i');
        }
      }

4.4 while 循环

  • while 循环如下所示

      void test() {
        int i = 0;
        while(i < 10) {print('$i');
          i++;
        }
      }
  • The classic for do while loop. 典型的 do while 循环。

      void test() {
        int i = 0;
        do {print('$i');
          i++;
        } while (i < 10);
      }

4.6 break 和 continue

4.7 switch 和 case

  • 代码如下所示

      void test() {
        int age = 50;
        switch(age) {
          case 10:
            print('Too Young.');
            break;
          case 20:
          case 30:
            print('Still Young!');
            break;
          case 40:
            print('Getting old.');
            break;
          case 50:
            print('You are old!');
            break;
        }
      }

05.Dart 面向对象

5.1 类简单介绍

  • 创建一个类和创建类的实例

    void test1(){Dog d = new Dog();
    }
    class Dog {
    
    }
    
    
    var cat = new Cat("逗比", 12);
    class Cat {
      String name;
      int age;
    
      Cat(String name, int age) {
        this.name = name;
        this.age = age;
      }
    }

5.2 构造函数

  • 普通构造函数

    var cat = new Cat("逗比", 12);
    
    class Cat {
      String name;
      int age;
    
      Cat(String name, int age) {
        this.name = name;
        this.age = age;
      }
    }
  • 命名构造函数

    • 给构造函数提供了名称,这样做使得不同的构造函数变的更加清晰。
    Map map = new Map();
    map['name']= "哈巴狗";
    map['age'] = 5;
    Dog d = new Dog.newBorn(map);
    
    
    class Dog {
      String name;
      int age;
    
      Dog(this.name, this.age);
    
      Dog.newBorn(Map json) {name = json['name'];
        age = json['age'];
      }
    }

5.3 继承类

  • 可以使用 extends 关键字继承其他的类。

    • Pug 类继承 Dog 类,通过 super 关键字调用 Dog 类的构造函数。
    Pug p = new Pug('逗比哈巴狗', 5);
    print(p.name);
    
    
    class Dog {
      String name;
      int age;
    
      Dog(this.name, this.age);
    
      Dog.newBorn() {
        name = 'Doggy';
        age = 0;
      }
    }
    
    class Pug extends Dog {Pug(String name, int age): super(name, age);
    }
  • 也可以通过 this 关键字,在冒号之后调用同一个类中的其他构造函数。

    • 定义了两个命名构造函数,他们只需要 dog 的名字,然后调用 Pug 的默认构造函数。
    Pug p = new Pug.small('傻逼');
    print(p.name);
    
    class Dog {
      String name;
      int age;
    
      Dog(this.name, this.age);
    
      Dog.newBorn() {
        name = '逗比哈巴狗';
        age = 0;
      }
    }
    
    class Pug extends Dog {Pug(String name, int age): super(name, age);
    
      Pug.small(String name): this(name, 1);
    
      Pug.large(String name): this(name, 3);
    }

5.4 重载和重写

  • 方法重写

    • 代码如下,最后打印值是:你真是个逗比
    Pug p = new Pug();
    print(p.bark());
    
    class Dog {bark() {print('Bow Wow');
      }
    }
    
    class Pug extends Dog {
      @override
      bark() {print('你真是个逗比!');
      }
    }
  • 方法重载

5.5 抽象类

  • 可以通过 abstract 关键字声明抽象类

    • 只需要在类声明前添加 abstract 关键字,方法不需要。方法只需要签名,不需要实现。
    abstract class AbstractDog {void eat();
      void _hiddenMethod();}
    
    class SmallDog extends AbstractDog{
      @override
      void _hiddenMethod() {}
    
      @override
      void eat() {}
    }

5.6 访问权限

  • 默认类中的所有属性和方法是 public 的。在 dart 中,可以在属性和方法名前添加“_”使私有化。现在让我们使 name 属性私有化。

    • 可以发现,调用私有化变量或者方法的时候会出现红色警告
      void test() {Dog d = new Dog('哈巴狗', 5);
        // 这个报错
        print(d.name);
        print(d.age);
      }
    • Dog 代码如下所示
    class Dog {
      String _name;
      int age;
    
      Dog(this._name, this.age);
    
      String get respectedName {return 'Mr.$_name';}
    
      set respectedName(String newName) {_name = newName;}
    
      Dog.newBorn() {
        _name = '哈巴狗';
        age = 0;
      }
    
      bark() {print('Bow Wow');
      }
    
      _hiddenMethod() {print('I can only be called internally!');
      }
    }

5.7 静态方法

  • 如果想让方法或者属性静态化,只需要在声明前添加 static 关键字。

    void test() {Dog.bark();
    }
    
    
    class Dog {static bark() {print('Bow Wow');
      }
    }

5.8 泛型

  • dart 全面支持泛型。假设你想在你定义的类中,想持有任意类型的数据。如下是怎样使用泛型定义这样的类。

    DataHolder<String> dataHolder = new DataHolder('Some data');
    print(dataHolder.getData());
    dataHolder.setData('New Data');
    print(dataHolder.getData());
    // 下面这个会报错,因为 dataHolder 对象在创建的时候就已经限制为 String 类型
    dataHolder.setData(123);
    print(dataHolder.getData());
    
    
    class DataHolder<T> {
      T data;
    
      DataHolder(this.data);
    
      getData() {return data;}
    
      setData(data) {this.data = data;}
    }

06.Dart 异步解读

6.1 Future 简单介绍

  • async 库中有一个叫 Future 的东西。Future 是基于观察者模式的。如果你熟悉 Rx 或者 JavaScript 的 Promises,你就很容易明白了。

    • 首先先看一下下面的案例,看看它们之间有什么区别?
      void testA() async{new Future<String>(() {return "This is a doubi";});
      }
    
      Future testB() async{return new Future<String>(() {return "This is a doubi";});
      }
    
      Future<String> testC() {return new Future<String>(() {return "This is a doubi";});
      }
6.1.1 普通异步案例
  • Future 是支持泛型的,例如 Future, 通过 T 指定将来返回值的类型。

    • 定义了一个叫 getTest 的函数,返回值为 Future<String>. 你可以通过 new 关键字创建一个 Future。Future 的构造函数,需要一个函数作为参数,这个函数返回 T 类型的数据。在匿名函数中的返回值就是 Future 的返回值。
    • 当调用了 getTest 方法,他返回 Future<String>. 我们通过调用 then 方法订阅 Future,在 then 中注册回调函数,当 Future 返回值时调用注册函数。同时注册了 catchError 方法处理在 Future 执行之间发生的异常。这个例子中不会发生异常。
      void test() {getTest().then((value) {print("测试 ----------"+value);
        }).catchError((error) {print('测试 ----------Error');
        });
      }
    
      Future<String> getTest() {return new Future<String>(() {return "This is a doubi";});
      }
      
      // 打印结果
      2019-06-21 17:11:12.941 16501-16583/com.hwmc.auth I/flutter: 测试 ----------This is a doubi
    • 下面这个案例会发生异常
      void test() {getTest().then((value) {print("测试 ----------"+value);
        }).catchError((error) {print('测试 ----------Error');
        });
      }
    
      Future<String> getTest() {return new Future<String>(() {return "This is a doubi";});
      }
      
      // 打印结果
      2019-06-21 17:18:46.896 16501-16583/com.hwmc.auth I/flutter: 测试 ----------Error
6.1.2 耗时异步案例
  • 在生产环境中都是一些耗时的操作,例如,网络调用,我们可以使用 Future.delayed()模仿。

    • 现在如果你运行,你将需要 2 秒,才能返回结果。
      void test() {getTest().then((value) {print("测试 ----------"+value);
        }).catchError((error) {print('测试 ----------Error');
        });
      }
    
      Future<String> getTest() {return new Future<String>.delayed(new Duration(milliseconds: 2000),() {return "This is a doubi";});
      }
    • 接下来再看一个案例。在调用函数之后,我们添加了 print 语句。在这种场景中,print 语句会先执行,之后 future 的返回值才会打印。这是 future 的预期行为. 但是如果我们希望在执行其他语句之前,先执行 future。
      void test() {getTest().then((value) {print("测试 ----------"+value);
        }).catchError((error) {print('测试 ----------Error');
        });
        print('测试 ---------- 逗比是这个先执行吗');
      }
    
      Future<String> getTest() {return new Future<String>.delayed(new Duration(milliseconds: 2000),() {return "This is a doubi";});
      }
      
      2019-06-21 17:26:16.619 16501-16583/com.hwmc.auth I/flutter: 测试 ---------- 逗比是这个先执行吗
      2019-06-21 17:26:17.176 16501-16583/com.hwmc.auth I/flutter: 测试 ----------This is a doubi

6.2 async/await 介绍

  • 思考一下,看了上面的案例,对于 future 的预期行为,如果我们希望在执行其他语句之前,先执行 future,该怎么操作呢?

    • 这就需要用到需要用到 async/await。在 test 函数的花括号开始添加 async 关键字。我们添加 await 关键字在调用 getTest 方法之前,他所做的就是在 future 返回值之后,继续往下执行。我们将整个代码包裹在 try-catch 中,我们想捕获所有的异常,和之前使用 catchError 回调是一样。使用 awiat 关键字,必须给函数添加 async 关键字,否则没有效果。
    • 注意:要使用 await,其方法必须带有 async 关键字。可以使用 try, catch, 和 finally 来处理使用 await 的异常!
      Future test() async {
        try {String value = await getTest();
          print("测试 ----------"+value);
        } catch(e) {print('测试 ----------Error');
        }
        print('测试 ---------- 逗比是这个先执行吗');
      }
    
      Future<String> getTest() {return new Future<String>.delayed(new Duration(milliseconds: 2000),() {return "This is a doubi";});
      }
      
      2019-06-21 17:32:37.701 16501-16583/com.hwmc.auth I/flutter: 测试 ----------This is a doubi
      2019-06-21 17:32:37.702 16501-16583/com.hwmc.auth I/flutter: 测试 ---------- 逗比是这个先执行吗

6.3 看一个案例

  • 一个 async 方法 是函数体被标记为 async 的方法。虽然异步方法的执行可能需要一定时间,但是 异步方法立刻返回 – 在方法体还没执行之前就返回了。

    void getHttp async {// TODO ---}
    • 在一个方法上添加 async 关键字,则这个方法返回值为 Future。

      • 例如,下面是一个返回字符串的同步方法:
      String loadAppVersion() => "1.0.2"
    • 使用 async 关键字,则该方法返回一个 Future,并且 认为该函数是一个耗时的操作。

      Futre<String> loadAppVersion() async  => "1.0.2"
    • 注意,方法的函数体并不需要使用 Future API。Dart 会自动在需要的时候创建 Future 对象。
  • 好的代码是这样的

    void main() {
     // 调用异步方法
     doAsync();}
    
    // 在函数上声明了 async 表明这是一个异步方法
    Future<bool> doAsync() async {
      try {
        // 这里是一个模拟请求一个网络耗时操作
        var result = await getHttp();
        // 请求出来的结果
        return printResult(result);
      } catch (e) {print(e);
        return false;
      }
    }
    // 将请求出来的结果打印出来
    Future<bool> printResult(summary) {print(summary);
    }
    
    // 开始模拟网络请求 等待 5 秒返回一个字符串
    getHttp() {return new Future.delayed(Duration(seconds: 5), () => "Request Succeeded");
    }
  • 不好的写法

    void main() {doAsync();
    }
    
    Future<String> doAsync() async {return  getHttp().then((r){return printResult(r);
        }).catchError((e){print(e);
        });
    }
    
    Future<String> printResult(summary) {print(summary);
    }
    
    Future<String> getHttp() {return new Future.delayed(Duration(seconds: 5), () => "Request Succeeded");
    }

07.Dart 异常捕获

7.1 异常处理形式

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

7.2 抛出异常

  • 看看如何抛出异常

      void test1(){divide(10, 0);
      }
    
      divide(int a, int b) {if (b == 0) {throw new IntegerDivisionByZeroException();
        }
        return a / b;
      }
    • 当 b 变量的值为 0 的时候,抛出一个内置的异常 IntegerDivisionByZeroException。
  • 如何定义异常日志呢?

    • 可以在异常中携带一个字符串信息。
      void test1(){divide(10, 0);
      }
    
      divide(int a, int b) {if (b == 0) {throw new Exception('逗比,不能为 0 的');
        }
        return a / b;
      }

7.3 捕获异常

  • 某种类型的异常可以通过 on 关键字捕获,如下:

      void test1(){
        try {divide(10, 0);
        } on IntegerDivisionByZeroException {print('逗比,异常被捕获了');
        }
      }
    
      divide(int a, int b) {if (b == 0) {throw new IntegerDivisionByZeroException();
        }
        return a / b;
      }
  • 注意问题,捕获的异常层级要大于抛出的异常,否则捕获会失败

    • 还是会抛出异常 ’ 逗比,不能为 0 的 ’,因为 Exception 比 IntegerDivisionByZeroException 层级要高。
      void test1(){
        try {divide(10, 0);
        } on IntegerDivisionByZeroException {print('逗比,异常被捕获了');
        }
      }
    
      divide(int a, int b) {if (b == 0) {throw new Exception('逗比,不能为 0 的');
        }
        return a / b;
      }
  • 如果你不知道抛出异常的类型,或者不确定,可以使用 catch 块处理任意类型的异常。

      void test1(){
        try {divide(10, 0);
        } on IntegerDivisionByZeroException {print('逗比,异常被捕获了');
        } catch (e) {print(e);
        }
      }
    
      divide(int a, int b) {if (b == 0) {throw new Exception('yc other exception.');
        }
        return a / b;
      }

7.4 Finally 讲解

  • dart 也提供了 finally 块,即是否发生异常这个块都会执行。

      void test1(){
        try {divide(10, 0);
        } on IntegerDivisionByZeroException {print('逗比,异常被捕获了');
        } catch (e) {print(e);
        }finally {print('I will always be executed!');
        }
      }
    
      divide(int a, int b) {if (b == 0) {throw new Exception('yc other exception.');
        }
        return a / b;
      }

08.Dart 枚举

8.1 枚举使用

  • dart 支持枚举,用法和 java 一样。

    Dog d = new Dog('哈巴狗', 12, CurrentState.sleeping);
    print(d.state == CurrentState.sleeping); //Prints 'true'
    
    
    enum CurrentState {
      sleeping,
      barking,
      eating,
      walking
    }
    
    class Dog {
      String name;
      int age;
      CurrentState state;
    
      Dog(this.name, this.age, this.state);
    
      static bark() {print('Bow Wow');
      }
    }

8.2 元数据

  • 使用元数据给代码添加额外信息,元数据注解是以 @字符开头,后面是一个编译时常量或者调用一个常量构造函数。
  • 有三个注解所有的 Dart 代码都可使用:@deprecated、@override,@proxy, 下面直接上 @deprecated 的示例:
  • 元数据可以在 library、typedef、type parameter、constructor、factory、function、field、parameter、或者 variable 声明之前使用,也可以在 import 或者 export 指令之前使用,使用反射可以再运行时获取元数据信息。

8.3 自定义注解

  • 定义自己的元数据注解。下面的示例定义一个带有两个参数的 @toDo 注解:

    void test1() {doSomething();
    }
    
    
    @toDo('seth', 'make this do something')
    void doSomething() {print('do something');
    }
    
    class toDo {
      final String who;
      final String what;
      const toDo(this.who, this.what);
    }

09.Dart 字符串

9.1 String 简单介绍

  • Dart 字符串是 UTF-16 编码的字符序列,可以使用单引号或者双引号来创建字符串:

    String str1 = '单引号字符串';
    String str2 = "双引号字符串";
    
    print(str1);        // 输出:单引号字符串
    print(str2);        // 输出:双引号字符串

9.2 单双引号互相嵌套

  • String 中单、双引号互相嵌套情况如下所示

    String str1 = '单引号中的" 双引号 "字符串';
    String str2 = "双引号中的' 单引号 '字符串";
    
    print("yc-str1--" + str1);
    print("yc-str2--" + str2);
    
    // 单引号里面有单引号,必须在前面加反斜杠
    String str3 = '单引号中的 \' 单引号 \'';
    String str4 = "双引号里面有双引号,\" 双引号 \"";
    print("yc-str3--" + str3);
    print("yc-str4--" + str4);
    • 打印值
    2019-06-21 17:52:07.722 16501-16583/com.hwmc.auth I/flutter: yc-str1-- 单引号中的 "双引号" 字符串
    2019-06-21 17:52:07.723 16501-16583/com.hwmc.auth I/flutter: yc-str2-- 双引号中的 '单引号' 字符串
    2019-06-21 17:52:07.723 16501-16583/com.hwmc.auth I/flutter: yc-str3-- 单引号中的 '单引号'
    2019-06-21 17:52:07.723 16501-16583/com.hwmc.auth I/flutter: yc-str4-- 双引号里面有双引号,"双引号"
  • 注意点::

    • 单引号嵌套单引号之间不允许出现空串(不是空格),双引号嵌套双引号之间不允许出现空串:
    //String str5 = '单引号'''' 单引号 ';  // 报错了,逗比
    String str6 = '单引号'' ''单引号';
    String str7 = '单引号''*''单引号';
    String str8 = "双引号"" ""双引号";
    String str9 = "双引号""*""双引号";
    //String str10 = "双引号"""" 双引号 ";   // 报错了,逗比
    print("yc-str6--" + str6);
    print("yc-str7--" + str7);
    print("yc-str8--" + str8);
    print("yc-str9--" + str9);
  • 打印值

    2019-06-21 17:56:21.847 16501-16583/com.hwmc.auth I/flutter: yc-str6-- 单引号 单引号
    2019-06-21 17:56:21.847 16501-16583/com.hwmc.auth I/flutter: yc-str7-- 单引号 * 单引号
    2019-06-21 17:56:21.847 16501-16583/com.hwmc.auth I/flutter: yc-str8-- 双引号 双引号
    2019-06-21 17:56:21.847 16501-16583/com.hwmc.auth I/flutter: yc-str9-- 双引号 * 双引号

其他介绍

01. 关于博客汇总链接

  • 1. 技术博客汇总
  • 2. 开源项目汇总
  • 3. 生活博客汇总
  • 4. 喜马拉雅音频汇总
  • 5. 其他汇总

02. 关于我的博客

  • github:https://github.com/yangchong211
  • 知乎:https://www.zhihu.com/people/…
  • 简书:http://www.jianshu.com/u/b7b2…
  • csdn:http://my.csdn.net/m0_37700275
  • 喜马拉雅听书:http://www.ximalaya.com/zhubo…
  • 开源中国:https://my.oschina.net/zbj161…
  • 泡在网上的日子:http://www.jcodecraeer.com/me…
  • 邮箱:yangchong211@163.com
  • 阿里云博客:https://yq.aliyun.com/users/a… 239.headeruserinfo.3.dT4bcV
  • segmentfault 头条:https://segmentfault.com/u/xi…
  • 掘金:https://juejin.im/user/593943…

博客汇总项目开源地址:https://github.com/yangchong2…

正文完
 0