Dart 学习笔记 基础(一)

1,253 阅读6分钟

笔记来源:

笔记意在快速入门,主要记录一些与Java不同的语法用法

基础

Hellol World

void main(){//main入口
	print("Hello World");
}

变量

  • 使用 var 申明变量

  • 不赋值时默认定义为dynamic类型,默认值为null,后期可多次赋值不同类型的变量

    var s;
    s = 10;
    s = "haha";
    
  • var 定义变量时直接赋值某一种类型变量,dart会通过类型推断确定变量类型,后期只能赋值同一类型变量

    var a = 10;
    a = 200;
    a = "aa"//编译错误
    
  • 关键字 final用来声明一个 只能赋值一次的变量 final str = "const variate";

  • dynamic Object

    dynamic声明的对象编译器会提供所有可能的组合, 而Object声明的对象只能使用Object的属性与方法, 否则编译器会报错

    dynamic d = "demo";
    d = 100;
    Object o = 200;
    o = "test";
    // dynamic 和 Object的差别
     print(d.length);
     print(o.length);//出错
    

常量

  • 使用 const 申明常量
  • const 申明的必须是编译期常量

数据类型

数值型-Number

  • 子类 整型Int浮点型double

  • 运算符 (+,-,*,/,~/,%)(加减乘除 取成 取余)

      int c = 20;
      double d = 10.5;
    
      print(c / d);
      print(c ~/d);
      print(c % d);
    
      print(0.0 /0.0);
      print(200.5/0);
    

    结果

    1.9047619047619047
    1
    9.5
    NaN
    Infinity
    

    后面两种特殊情况,在double中的源码:

    abstract class double extends num {
      static const double nan = 0.0 / 0.0;
      static const double infinity = 1.0 / 0.0;
      static const double negativeInfinity = -infinity;
      static const double minPositive = 5e-324;
      static const double maxFinite = 1.7976931348623157e+308;
      ....
      }
    
  • 常用属性

    • isNaN 是否非数字
    • isEven 是否奇数
    • isOdd 是否偶数
  • 常用方法

    • abs() 绝对值
    • round() 四舍五入
    • floor() 取最小整数
    • ceil() 取最大整数
    • toInt()
    • toDouble()

字符串-String

创建字符串
  • 单引号 双引号
  • 三个引号 或 双引号 创建多行字符串
  • 使用r创建原始raw 字符串
  //普通赋值
  String str1 = 'hello world';
  //保留格式
  String str2 = '''Hello
                    Dart''';
  print(str2);
  // 转义符
  String str3 = 'hello \n Dart';
  print(str3);
  // r 保留字符串原型
  String str4 = r'hello \n Dart';
  print(str4);

输出:

Hello
                    Dart
hello 
 Dart
hello \n Dart
运算符(+、*、==、[])
  String str5 = "hello ";
  //拼接
  print(str5+" add");
  // 真的 是乘
  print(str5 * 6);
  // ==
  print(str5 == str4);
  //取第一个字符
  print(str5[0]);

输出:

hello  add
hello hello hello hello hello hello 
false
h
插值表达式 ${expression}
  int a = 1;
  int b = 2;
  print("$a + $b = ${a + b}");

输出:

1 + 2 = 3

字符串常用方法大致与Java类似 略

布尔型-Boolean

​ 定义:bool isTrue = true;

列表(数组)-List

创建
  • 简单创建:var list = [1,2,3,"dart",true];
  • 创建不可变list :var list = const[1,2,3,"dart",true];
  • 构造创建:var list = new List();
常见操作
  • []、length
  • indexOf() lastIndexOf()
  • add() insert()
  • sort() sublist()
  • remove() clear()

以上都与Java集合操作类似 略过

  • asMap() 直接使用list的下标为key value 为值

  • shuffle(),forEach()

    • forEach()源码 直接接收方法
      void forEach(void f(E element)) {
        for (E element in this) f(element);
      }
    

    eg:

      var list = [2,3,"haha",true];
      print(list);
      list.forEach(print); 
    

    输出:

    [2, 3, haha, true]
    2
    3
    haha
    true
    

键值对-Map

创建
  • 简单创建: var language = {'first':'Dart','second','Java',1:true,true:2};
  • 创建不可变Map:var language = const {'first':'Dart','second','Java'};
  • 构造创建: var language = new Map();

常用操作

  • []、length、containKey()、 containValue()、 isEmpty()、 isNotEmpty()、 remove()、 key、values、 forEach()

dynamic 动态类型

目前仅知道可用于泛型中,代表泛型可接收不同类型的数据

运算符(加粗的时特有的,其它与Java一样)

  • a++,++a,a--,--a 与Java 一样,先使用a后计算 和 先计算 后使用a
  • ==、!=、>、<、>=、<=
  • !、&&、||
  • =、??=、+=、-=、*=、/=、~/=、%=
    • num ??= 10 : 如果num为空 则赋值10,否者不进行赋值
  • 三目运算符:condition?expr1:expr2;
  • ?? 运算符: expr1??expr2;
    • String data = a ?? b; 赋值时 如果 a为空 则将b 的值赋值给data,如果a不等于空 则使用a 的值赋值

控制语句

  • if else
  • for 、for...in
  • while 、do...while...
  • break、contain
  • switch..case..
    • 比较类型:num、String、编译器常量、对象、枚举
    • 非空case必须有一个break
    • default
    • contain跳转标签

方法

  • 定义

    返回类型 方法名(参数1,参数2,...){
    	方法体
    	return 返回值;
    }
    
  • 特性

    • 方法也是对象,并且有具体类型Function
    • 返回值类型、参数类型都可省略
    • 箭头语法:=> expr 是 {return expr;}的缩写。只适用与一个表达式
    • 方法都有返回值。如果没有指定,默认return null最后一句

eg: 两种写法效果一样

String getPreson(String name,int age){
  return "name:$name age:$age";
}

printPerson(name,age) => "name:$name age:$age";
  • 可选参数(如果有固定参数必须放在固定参数的后面)

    priPerson("王五",gender: "haha");
    priPerson2("wanwu",25);
    //大括号的可选参数,传参时根据参数名称来调用
    priPerson(String name,{int age,String gender}){
      print("name=$name,age=$age,gender=$gender");
    }
    //中括号的可选参数,传参根据所在位置来
    priPerson2(String name,[int age,String gender]){
      print("name=$name,age=$age,gender=$gender");
    }
    

    输出:

    name=王五,age=null,gender=haha
    name=wanwu,age=25,gender=null
    
  • 默认参数值

    priPerson(String name,{int age = 30,String gender = "haha"}){
      print("name=$name,age=$age,gender=$gender");
    }
    
  • 方法对象

    • 方法可作为对象赋值给其它变量

      var fun1 = printHello;
      fun1();
          
      void printHello(){
        print("Hello");
      }
      
    • 方法可作为参数传递给其它方法

      List data = ['a','b','c','d'];
      timesList(data, times);
      print(data);
      
      //将原先的集合中的元素重复三次
      List timesList(List data,fun(String str)){
        for(var i = 0;i<data.length;i++){
          data[i] = fun(data[i]);
        }
        return data;
      }
      //重复字符串三次
      String times(String str){
        return str * 3;
      }
    
  • 匿名方法

    • 可赋值给变量,通过变量进行调用

      var fun = (name){
      		print("hei $name");
          };
      //调用
      fun();
      
    • 可在其它方法中直接调用或传递给其它方法

      timesList(data, (str){return str*3;});
      
      List timesList(List data,fun(String str)){。。。
       }
      
  • 闭包

    • 闭包是一个方法(对象)

    • 闭包定义在其它方法内部

    • 闭包能够方法外部方法内的局部变量,并持有其状态

      closePackage(){
      int count = 0;
      printCount(){
        print(count++);
      }
      return printCount();
      }
      

枚举

  • 枚举是一种有穷序列集的数据类型
  • 使用关键字 enum 定义一个枚举
  • 常用来代替常量,控制语句等
  • 枚举有角标index 从0开始

异步

  • Dart类库有非常多的返回Future或者Stream对象的函数。 这些函数被称为异步函数
  • asyncawait关键词支持了异步编程,允许您写出和同步代码很像的异步代码

Future

  • 基本的异步用户
Future.delayed(new Duration(seconds: 2),(){
   //return "hi world!";
   throw AssertionError("Error");
}).then((data){
   //执行成功会走到这里 
   print(data);
}).catchError((e){
   //执行失败会走到这里   
   print(e);
}).whenComplete((){
   //无论成功或失败都会走到这里
});
  • Future.wait
Future.wait([//等待所有任务完成后
  // 2秒后返回结果  
  Future.delayed(new Duration(seconds: 2), () {
    return "hello";
  }),
  // 4秒后返回结果  
  Future.delayed(new Duration(seconds: 4), () {
    return " world";
  })
]).then((results){
  print(results[0]+results[1]);
}).catchError((e){
  print(e);
});
  • 链式调用,避免层层嵌套
login("alice","******").then((id){
      return getUserInfo(id);
}).then((userInfo){
    return saveUserInfo(userInfo);
}).then((e){
   //执行接下来的操作 
}).catchError((e){
  //错误处理  
  print(e);
});
  • async/await 向写同步任务一样写异步
task() async {//async用来表示函数是异步的,定义的函数会返回一个Future对象,可以使用then方法添加回调函数。
   try{
    //await 后面是一个Future,表示等待该异步任务完成,异步完成后才会往下走;await必须出现在 async 函数内部。
    String id = await login("alice","******");
    String userInfo = await getUserInfo(id);
    await saveUserInfo(userInfo);
    //执行接下来的操作   
   } catch(e){
    //错误处理   
    print(e);   
   }  
}

Stream

Stream 也是用于接收异步事件数据,和Future 不同的是,它可以接收多个异步操作的结果(成功或失败)。 也就是说,在执行异步任务时,可以通过多次触发成功或失败事件来传递结果数据或错误异常。 Stream 常用于会多次读取数据的异步任务场景,如网络内容下载、文件读写等

Stream.fromFutures([
  // 1秒后返回结果
  Future.delayed(new Duration(seconds: 1), () {
    return "hello 1";
  }),
  // 抛出一个异常
  Future.delayed(new Duration(seconds: 2),(){
    throw AssertionError("Error");
  }),
  // 3秒后返回结果
  Future.delayed(new Duration(seconds: 3), () {
    return "hello 3";
  })
]).listen((data){
   print(data);
}, onError: (e){
   print(e.message);
},onDone: (){

});

输出:

I/flutter (17666): hello 1
I/flutter (17666): Error
I/flutter (17666): hello 3