YANGDAHUAN 2019-07-01
01.变量声明
02.数据类型
03.Dart函数和运算符
04.Dart流程控制
05.Dart面向对象
06.Dart异步解读
6.1 Future简单介绍
07.Dart异常捕获
08.Dart枚举
09.Dart字符串
个人信息
关于近期投递简历一点感想
类似于kotlin中的var,它可以接收任何类型的变量,但最大的不同是Dart中var变量一旦赋值,类型便会确定,则不能再改变其类型,如:
var t; t="yc"; // 下面代码在dart中会报错,因为变量t的类型已经确定为String, // 类型一旦确定后则不能再更改其类型。 t=1000;
变量如下所示
var curPage = 0; var title = "潇湘剑雨:小杨逗比";
const 的值在编译期确定,final 的值要到编译时才确定。
Dart 中 final 表示常量
//final 表示常量 final title = "潇湘剑雨:小杨逗比";
static const 组合代表了静态常量
//static const 组合代表了静态常量 static const String complete = "COMPLETE";
final和const区别
const 变量是一个编译时常量,final变量在第一次使用时被初始化。被final或者const修饰的变量,并且变量类型可以省略。注意点
//定义初始化一个变量 final double number = 13.14; number = 520; //调用打印数字方法 printNumber(number);
在Java中可以直接通过 + 号将字符串和int类型拼接,但是在Dart中是不行的。
//在Java中,下面操作可行
ToastUtils.showRoundRectToast("二维码扫描"+1000);
//在dart中,下面错误操作,编译不通过,直接会有红色提示
int yc = 0;
print("潇湘剑雨" + yc);
//在dart中,下面正确操作
int yc = 0;
print("潇湘剑雨" + yc.toString());Object 是dart所有对象的根基类,也就是说所有类型都是Object的子类(包括Function和Null),所以任何类型的数据都可以赋值给Object声明的对象.
dynamic与var一样都是关键词,声明的变量可以赋值任意对象.而dynamic与Object相同之处在于,他们声明的变量可以在后期改变赋值类型.dynamic t; Object x; t = "hi world"; x = 'Hello Object'; //下面代码没有问题 t = 1000; x = 1000;
dynamic与Object不同的是,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的这个特点使得我们在使用它是需要格外注意,这很容易引入一个运行时错误.var 可以定义变量,同时 Dart 属于动态类型语言,支持闭包。
//int类型 这里没有long类型 var positionIndex = 0; //double类型 这里没有float类型 var time = 1993.03;
//定义初始化一个变量 double number = 13.14;
Dart 下只有 bool 型可以用于 if 等判断,不同于 JS 这种使用方式是不合法的 var g = "null"; if(g){} 。
//类似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);
}// 检查是否为空字符串 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);
Dart 中,switch 支持 String 类型。后面会单独拿出来讲解一下。
//字符串 var title = "潇湘剑雨:小杨逗比";
声明一个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);
}如果你想定义一个编译时常量list,例如,list的内容是不可改变的,可以使用关键字const
var list = const [1,2,3,4];
定义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。
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逗比
dart中的函数和JavaScript中有点类似。你需要定义就是函数的名字、返回值(有返回值或者void)、参数。
void test(){
    var name = fullName('杨充', '逗比');
    print(name);
  }
  String fullName(String firstName, String lastName) {
    return "$firstName $lastName";
  }dart有个叫命名参数的东西。当你调用函数的时候,你必须指定参数的名字。要使用命名参数,可以将函数的参数包括在花括号{}内。
void test(){
    var name = fullName('杨充', '逗比');
    print(name);
  }
  String fullName(String firstName, String lastName) {
    return "$firstName $lastName";
  }你可以给函数的命名参数一个默认值。下面的例子给lastName一个默认值。
void test(){
    var name = fullName('杨充', '逗比');
    print(name);
  }
  fullName(String firstName, String lastName) {
    return "$firstName $lastName";
  }在dart中函数比较灵活,例如,你可以将函数当参数传递给另一个函数。
void test(){
    out(printOutLoud);
  }
  out(void inner(String message)) {
    inner('Message from inner function');
  }
  printOutLoud(String message) {
    print(message.toUpperCase());
  }另一个匿名函数的例子。
大概有这么多
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 ? "年轻人" : "老年人";
for循环和java几乎是一样的,代码如下
void test() {
    for (int i = 0; i < 10; i++) {
      print('$i');
    }
  }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);
  }代码如下所示
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;
    }
  }创建一个类和创建类的实例
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;
  }
}普通构造函数
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'];
  }
}可以使用extends关键字继承其他的类。
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关键字,在冒号之后调用同一个类中的其他构造函数。
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);
}方法重写
Pug p = new Pug();
print(p.bark());
class Dog {
  bark() {
    print('Bow Wow');
  }
}
class Pug extends Dog {
  @override
  bark() {
    print('你真是个逗比!');
  }
}方法重载
可以通过abstract关键字声明抽象类
abstract class AbstractDog {
  void eat();
  void _hiddenMethod();
}
class SmallDog extends AbstractDog{
  @override
  void _hiddenMethod() {
    
  }
  @override
  void eat() {
    
  }
}默认类中的所有属性和方法是public的。在dart中,可以在属性和方法名前添加“_”使私有化。现在让我们使name属性私有化。
void test() {
    Dog d = new Dog('哈巴狗', 5);
    //这个报错
    print(d.name);
    print(d.age);
  }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!');
  }
}如果想让方法或者属性静态化,只需要在声明前添加static关键字。
void test() {
  Dog.bark();
}
class Dog {
  static bark() {
    print('Bow Wow');
  }
}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;
  }
}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";
    });
  }Future是支持泛型的,例如Future,通过T指定将来返回值的类型。
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 doubivoid 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在生产环境中都是一些耗时的操作,例如,网络调用,我们可以使用Future.delayed()模仿。
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";
    });
  }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思考一下,看了上面的案例,对于future的预期行为,如果我们希望在执行其他语句之前,先执行future,该怎么操作呢?
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: 测试----------逗比是这个先执行吗一个 async 方法 是函数体被标记为 async 的方法。 虽然异步方法的执行可能需要一定时间,但是 异步方法立刻返回 - 在方法体还没执行之前就返回了。
void getHttp async {
    // TODO ---
}在一个方法上添加 async 关键字,则这个方法返回值为 Future。
String loadAppVersion() => "1.0.2"
使用 async 关键字,则该方法返回一个 Future,并且 认为该函数是一个耗时的操作。
Futre<String> loadAppVersion() async => "1.0.2"
好的代码是这样的
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");
}看看如何抛出异常
void test1(){
    divide(10, 0);
  }
  divide(int a, int b) {
    if (b == 0) {
      throw new IntegerDivisionByZeroException();
    }
    return a / b;
  }如何定义异常日志呢?
void test1(){
    divide(10, 0);
  }
  divide(int a, int b) {
    if (b == 0) {
      throw new Exception('逗比,不能为0的');
    }
    return a / b;
  }某种类型的异常可以通过on关键字捕获,如下:
void test1(){
    try {
      divide(10, 0);
    } on IntegerDivisionByZeroException {
      print('逗比,异常被捕获了');
    }
  }
  divide(int a, int b) {
    if (b == 0) {
      throw new IntegerDivisionByZeroException();
    }
    return a / b;
  }注意问题,捕获的异常层级要大于抛出的异常,否则捕获会失败
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;
  }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;
  }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');
  }
}定义自己的元数据注解。下面的示例定义一个带有两个参数的@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);
}Dart字符串是UTF-16编码的字符序列,可以使用单引号或者双引号来创建字符串:
String str1 = '单引号字符串'; String str2 = "双引号字符串"; print(str1); //输出:单引号字符串 print(str2); //输出:双引号字符串
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--双引号*双引号