Dart语言入门介绍

Dart诞生于2011年10月10日,google Dart语言项目的领导人Lars Bak在丹麦举行的Goto会议上宣布,
Dart是一种结构化的web编程语言,它被ECMA认定为标准,用于Web、服务器、移动应用和物联网等领域的开发,
是宽松开源许可证下的(开源软件)。
Dart适合用于移动开发的特性:
1:Dart是AOT(Ahead Of Time)编译的编译成快速,可预测的本地代码,
使Flutter几乎都可以使用Dart编写,这不仅使Flutter变得更快,而且几乎所有的组件都可以定制。
2:Dart也可以JIT(Just In Time)编译,开发周期快,
3:Dart可以更轻松的创建以60fps运行的流畅动画和转场。Dart可以在没有锁的情况下进行
对象分配和垃圾回收,就像js一样,Dart避免了抢占式调度和共享内存,由于Flutter应用程序
被编译为本地代码,因此不需要再领域之间建立缓慢的桥梁,他的启动速度也快的多。
4:Dart使Flutter不需要单独的声明式布局语言(JSX或XML)或单独的可视化构建器,
因为Dart的声明式编程布局易于阅读和可视化,所有的布局使用一种语言,聚集在一处,使布局更简单。
Dart重要概念
1:所有的东西都是对象,无论是变量 数字 函数都是对象,所有的对象都是类的实例,
所有的对象都集成自内置的Object类,类似于java语言 “一切皆对象”。
2:程序中指定数据类型使得程序合理的分配内存空间,并帮助编译器进行语法检查,
但是,指定类型不是必须的,Dart语言是弱数据类型
3:Dart代码在运行前解析,指定数据类型和编译时常量,可以提高运行速度。
4:Dart有统一的程序入口main()
5:Dart没有public、protected和private的概念,私有特性通过变量或函数加上下划线来表示
6:Dart支持anync/await异步处理
7:Dart语言常用库
dart:async 异步编程支持,提供Future和Stream
dart:collection 对dart:core提供更多的集合支持
dart:convet 不同类型(JSON UTF-8)间的字符编码、解码支持
dart:core Dart语言内建类型、对象以及dart语言核心的功能
strings,numbers,collections,errors,dates,URIs
dart:html 网页开发用到的库
dart:io 文件读写I/O相关的库
dart:math 数字常量及函数,提供随机数算法
dart:svg事件和动画的矢量图向支持

使用官方提供的pub工具可以安装丰富的第三方库:pub.dartlang.org
在pubspec.yaml文件中添加要依赖的某个版本的三方库,然后点击右上角Packages get
写在dependencies下边

dart基本数据类型
Number:数值类型 num的两个子类int和double,基本方法包括abs,ceil,floor,+,-,*,/等
String:字符串类型 可以用单引号’fff’,也可以使用双引号"fff"
Boolean:bool flag = true;Dart中的布尔类型用法同Java,仅有false、true两个值,不能使用0、非0或者null、非null来表达false和true。与Java不同的是,布尔类型的默认值为null
List:列表:在dart语言中,具有一系列相同类型的数据被称为List对象
Map:映射:将key和value关联在一起,也就是键值对,key必须是唯一的

一、定义变量:

//显式定义变量
String name = '张三';
num age = 18;
//使用var关键字
var address = '王府井大街';
var id = 100;
使用var定义变量,即使未显式指定类型,一旦赋值后类型就被固定
因此使用var定义的变量不能改变数据类型
var number = 19;
// 以下代码错误,无法运行,number变量已确定为int类型
number = "2019";
如想动态改变变量的数据类型,应当使用dynamic或Object来定义变量。
// dynamic声明变量
dynamic var1 = "hello";
var1 = 19;
print(var1);    // 19
// Object声明变量
Object var2 = 20;
var2 = "Alice";
print(var2);    // Alice

二、常量:
Dart中定义常量也有两种方式,一种使用final关键字,同Java中的用法, 一个 final 变量只能赋值一次;
另一种是Dart的方式,使用const关键字定义

// 1.使用final关键字定义常量
final height = 10;
// 2.使用const关键字定义常量
const pi = 3.14;

final定义的常量是运行时常量,而const常量则是编译时常量,
也就是说final定义常量时,其值可以是一个变量,而const定义的常量,其值必须是一个字面常量值。

final time = new DateTime.now(); // 正确
const time = new DateTime.now(); // 错误

const list = const[1,2,3];       // 正确
const list = [1,2,3];            // 错误

三、类型转换:

// String 转 int
var one = int.parse('1');
// String 转 double
var onePointOne = double.parse('1.1');
// int 转 String
String oneAsStr = 1.toString();
// double 转 String
String piAsStr = 3.14159.toStringAsFixed(2); // 保留两位 '3.14'

四、字符串:String
1.Dart可以使用单引号或双引号来创建字符串

var s1 = "hello";
var s2 = 'world';

2.类似Python,Dart可以使用三引号来创建包含多行的字符串

var multiLine1 = """你可以像这样,创建一个
包含了多行的字符串内容
""";
var multiLine2 = '''你也可以使用三个单引号,创建一个
包含了多行的字符串内容
''';

3.类似Python,还可以在字符串字面值的前面加上r来创建原始字符串,则该字符串中特殊字符可以不用转义

var path = r'D:\workspace\code';

// 4.Dart支持使用"+"操作符拼接字符串

var greet = "hello" + " world";

5.Dart提供了插值表达式"${}",也可以用于拼接字符串

var name = "王五";
var aStr = "hello,${name}";
print(aStr);    // hello,王五

// 当仅取变量值时,可以省略花括号
var aStr2 = "hello,$name"; // hello,王五

// 当拼接的是一个表达式时,则不能省略花括号
var str1 = "link";
var str2 = "click ${str1.toUpperCase()}";
print(str2);   // click LINK
  1. 与Java不同,Dart使用"=="来比较字符串的内容
print("hello" == "world");

五、列表:List

// 创建列表
var list = [1, 2, 3];
// 下标从0开始。使用length可以访问list的长度
print(list[0]);
print(list.length);

// 可以使用add添加元素
list.add(5);

可在list字面量前添加const关键字,定义一个不可改变的 列表(编译时常量)

var constantList = const [1, 2, 3];
constantList[1] = 1;     // 报错

六、映射:Map:
1.通过字面量创建Map

var gifts = {
  'first' : 'partridge',
  'second': 'turtledoves',
  'fifth' : 'golden rings'
};

2.使用Map类的构造函数创建对象

var pic = new Map();
// 往Map中添加键值对
pic['first'] = 'partridge';
pic['second'] = 'turtledoves';
pic['fifth'] = 'golden rings';

3.获取Map的长度

print(pic.length);

4.查找Map

pirnt(pic["first"]);
print(pic["four"]);    // 键不存在则返回 null

七、函数:Function
1.在Dart中,函数(或方法) 也是对象,它的类型是 Function。 这意味着,函数可以赋值给变量,也可以当做其他函数的参数。
2.函数也是对象,所有函数都有返回值。当没有指定返回值的时候,函数会返回null。当然,如果你强行使用void来修饰函数,则函数真的没有返回值,这种情况就另当别论了
3.参数类型可以显示的指定也可以隐藏,仍然建议显式的指定类型

//跟java类似
String greet(String name){
    return "hello,$name";
}
//省去返回值跟参数类型
greet(name){
    return "hello,$name";
}

7.2在java中通常是通过函数的重载来实现同名函数的不同调用,在Dart中可以通过可选参数来实现,可选参数有两种:
命名可选参数{}
位置可选参数[]

1:命名参数:{}参数放在大括号里,参数可以有默认值

// 定义一个函数,参数列表用花括号包裹
enableFlags({bool bold, bool hidden}) {
    // do something
}

// 调用方式,传参时使用"参数名:值"的形式
enableFlags(hidden:true,bold:false);

//给命名参数设置默认值
//定义add函数 @required设置该可选参数必填 可以不设置
add({@required int x, int y=1, int z=0}){
    print(x + y + z);
}
// 调用
add(x:18);              // 19
add(x:18, y:2, z:10);   // 30

定义命名参数时,你可以以 {type paramName} 或者 {paramName: type} 两种方式声明参数,而调用命名参数时,
需要以 funcName(paramName: paramValue) 的形式调用。
命名参数的参数并不是必须的,所以上面的代码中,不带任何参数,也是可以的,在Flutter开发中,
你可以使用@required注解来标识一个命名参数,这代表该参数是必须的,你不传则会报错
2:位置参数:
使用中括号[]括起来的参数是函数的位置参数,代表该参数可传可不传,位置参数只能放在函数的参数列表的最后面

add(int x, [int y, int z]){
	int result = x;
	if (y !=  null){
	      result = result + y;
	}
	if (z !=  null){
		result = result + z;
	}
	print(result);
}
调用:
add(18);           // 18
add(18,12);        // 30
add(18, 12, 15);   // 45

给位置参数设置默认值

// 定义add函数
add(int x, [int y=0, int z=0]){
    print(x +y+z);
}

命名可选参数与位置可选参数的区别:命名可选参数中的参数与顺序无关,无需按顺序传参,且传参数时需使用冒号;后者与顺序相关,传参必须依照顺序。
3:匿名函数
大部分函数都有名字,但我们也可以创建没有名字的函数,称为匿名函数,也被称为lambda表达式或者闭包。
// 定义匿名函数,并将其赋值给一个变量func,注意,函数体最后的花括号处必须有分号结束。

var func = (x,y){
    return x + y;
};
print(func(10,11));    // 21

匿名函数中如果参数使用不到可以使用(_)来代替
4:箭头函数
Dart中的箭头函数+与JavaScript中的基本相同。当函数体中只包含一个语句时,我们就可以使用=>箭头语法进行缩写。注意,箭头函数仅仅只是一个简洁表达的语法糖。

add(num x, num y){
    return x + y;
}
print(add(18,12));    // 30
等价于:
// 与上面的普通函数完全等价
add(num x, num y) => x + y;

print(add(18,12));    // 30
匿名箭头函数:
var func = (num x, num y) => x + y;

匿名函数中如果参数使用不到可以使用(_)来代替
typeof
从英文翻译的意思是 类型.其实可以说成是等同于某种类型,typeof就像是具有修饰特性的词语一样,指定某一类东西的类型

比如 :
typeof int add;     //那么此时add表示的是它是一个可以声明int的类型.
举个例子
我需要声明一个变量temp是int类型,我们常常是这样写的
int temp =0; //假设temp 给它赋值是0
那么同样,我也可以这样写
typeof int add;
add temp =0; //这样写其实也是可以的.
我定义一个这样的类型
typeof  int Add(int a, int b);
那么这个定义的应该怎么解释呢?!
声明 Add是一个带有两个int参数并且返回值是int类型的函数类型.

void main() {
  print(plusNum is Add);
}

int plusNum(int x, int y) {
  return x + y;
}
打印:
true

八、dart操作符
运算符:
Dart语言入门介绍_第1张图片三目运算符与非空判断
Dart语言入门介绍_第2张图片级联运算符:…
级联运算符可以在同一个对象上连续调用多个方法以及访问成员变量。 使用它可以避免创建临时变量, 写出更流畅的代码

new Person()..setName("Bob")..setAge(20)..save();

条件成员访问符
条件成员访问符?.它和.类似,但是运算符左边的对象不能为null,否则返回null,若对象不为null,则返回对象本身。

// list1默认值为null
List list1;
print(list1?.length);  // null

List list2 = [];
print(list2?.length);// 0

if与switch:基本跟java相同

if(i < 0){
  print('i < 0');
}else if(i == 0){
  print('i = 0');
} else {
  print('i > 0');
}

在switch的case中可以使用整数、字符串、枚举类型和编译时常量

String command = 'OPEN';
switch (command) {
  case 'CLOSED':
    break;
  case 'OPEN':
    break;
  default:
    print('Default');
}

九、循环:

// for循环
for(int i = 0; i < 9; i++) {
  print(i);
}
var myList = ['Java','JavaScript','Dart'];

// for...in...循环,类似Java中的增强for
for (var it in myList ){
    print(it);
}

// forEach循环。其参数为一个Function对象,这里传入一个匿名函数
myList.forEach((var it){
    print(it);
});

// 可以使用匿名箭头函数简写
myList.forEach((it) => print(it));

var myMap = {
'zhangsan':'201901',
'lisi':'201902',
'wangwu':'201902'
};

// forEach遍历Map
myMap.forEach((k, v) =>  print("$k : $v"));

// 根据键获取值来遍历。通过keys返回Map中所有键的集合
for(var k in myMap.keys){
    print("$k : ${myMap[k]}");
}

跟java不同,dart可以循环序列化的数据,跟python相同
十、关于异常
跟java不同,dart的所有异常都是未检查的异常,方法不声明他们可能抛出某些异常
Dart语言入门介绍_第3张图片十一、关于面向对象
Dart中的类与Java中的相似,不同的是,Dart中没有private、public这些成员访问修饰符。如果是类私有的成员,不希望外面访问,只需要在成员变量之前加上一个下划线_变为私有即可。
Dart中定义一个类

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

Dart中定义一个类

class  Person {
    String name;
    int age;
    // 在构造方法中初始化成员变量时,可使用如下写法简化
    Person(this.name, this.age);
    
    // 如需处理其他变量时,也可单独对其操作
    // Person(this.name, this.age, String address){
    //     print(address);
    // }
    // 注意,构造方法不能重载,以上注释掉
}

Dart中没有构造方法的重载,不能写两个同名的构造方法
Getters 和 Setters方法
Dart语言入门介绍_第4张图片
要注意,在创建对象时,new关键字并不是必须的,可以省略不写。在写Flutter界面时,不建议写new关键字实例化对象,因为Flutter框架中没有类似的xml语言来描述UI界面,界面也是使用Dart语言来写,在使用Dart写UI时,要保持代码的简洁和结构化,省略new会更友好。
构造方法
如果没有定义构造方法,则会有一个默认的无参构造方法,并且会调用超类的无参构造方法。

命名构造方法
上面已经说过,Dart类中两个同名构造方法不能重载,但是Dart语言为类新增了一种称为命名构造方法的东西。
Dart语言入门介绍_第5张图片
构造方法重定向
有时候一个构造方法会调动类中的其他构造方法来实例化,这时候可以使用构造方法重定向,Dart语言入门介绍_第6张图片类的初始化列表
熟悉C++的朋友应该对初始化列表很了解了,Java中是没有这个特性的。
Dart语言入门介绍_第7张图片
类的继承
Dart中的继承,与Java中相似,可以使用关键字extends继承父类,使用关键字super引用父类

class Human {
	  String name;
	  Human.fromJson(Map data) {
	    print("Human's fromJson constructor");
	  }
       }
class Man extends Human {
	  Man.fromJson(Map data) : super.fromJson(data) {
	    print("Man's fromJson constructor");
	  }
}
//由于Human类没有默认构造方法,只有一个命名构造方法fromJson,所以在Man类继承Human类时,
//需要调用父类的fromJson方法做初始化,而且必须使用Man.fromJson(Map data) : super.fromJson(data)这种写法,
//而不是像Java那样将super写到花括号中。

Java中的类仅支持单继承,而Dart中的类可以实现多继承。要实现多继承,需要使用with关键字,Mins(混入功能)相当于多继承
Dart语言入门介绍_第8张图片
抽象类
Dart语言没有提供interface关键字来定义接口,但是Dart语言中保留了抽象类,同Java,使用abstract关键字来修饰抽象类。而Dart中的抽象类,实际上就相当于Java中的接口。抽象类是不能被实例化的,子类继承抽象类时,必须实现全部抽象方法

//抽象类 抽象方法
abstract class Doer{
	  // 抽象方法,没有方法体,需要子类去实现
      void doSomething();
	  // 普通的方法
	  void greet() {
	    print("hello world!");
	  }
}
class EffectiveDoer extends Doer{
	  @override
	  void doSomething() {
	    print("瞎比实现");
	  }
	  @override
	  void greet() {
	    super.greet();
	  }
}

枚举类:

enum Color{
    red,green,blue
}
获取枚举中所有的值使用Value常数
Listcolors = Color.values;
通常用于switch语句
Color aColor = Color.blue;
switch(aColor){
     case Color.red::
     break;
     case Color.green:
     break;
}

泛型
dart中的泛型一般用于List或者Map等里边,跟java相同
Dart语言入门介绍_第9张图片
十二、关于库的引用
1.在import语句后边需要接上库文件路径
2.对dart语言提供的库文件使用dart:xx格式
3.第三方库文件使用package:xx格式
例如:

import 'dart:io'
import 'package:mylib/mylib.dart'
import 'package:utils/utils.dart'

4.指定一个库的前缀
当引用的库拥有相互冲突的名字,可以为其中一个或几个指定不一样的前缀,类似于命名空间
比如:

improt 'package:lib1/lib1.dart';
improt 'package:lib2/lib2.dart' as lib2;
Element element1 = new Element();//使用lib1里边的Element
lib2.Element element2 = new lib2.Element();//使用lib2里边的Element

5.引用库的一部分
如果只需要使用库的一部分内容,可以有选择的引用
5.1 show关键字:只引用一点
5.2 hide关键字:除此之外都引用

import 'package:lib1/lib1.dart' show foo;
import 'package:lib2/lib2.dart' hide foo;

十三、http请求
方式一

http: ^0.11.0
import 'package:http/http.dart' as http;
var url = 'http://httpbin.org/';
              //向上述地址发起get请求
              http.get(url).then((response) {
                print("状态:${response.statusCode}");
                print("正文:${response.body}");
              });

方式二

import 'dart:convert';
import 'dart:io';
void getWeatherData() async {
    try {
      //实例化一个httpclient对象
      HttpClient httpClient = new HttpClient();
      //发起请求
      //-----------------------------
      /*Uri uri = Uri(scheme: 'http',host: "t.weather.sojson.com",queryParameters: {
        "_id":26,
        "city_code":"101030100",
        "city_name":"天津"
      });
      HttpClientRequest request = await httpClient.getUrl(uri);*/
      //-----------------------------
      HttpClientRequest request = await httpClient.getUrl(Uri.parse("http://t.weather.sojson.com/api/weather/city/101030100"));
      //等待服务器返回数据
      HttpClientResponse response = await request.close();
      //使用utf8.decoder从response里解析数据
      var result = await response.transform(utf8.decoder).join();
      //输出响应头
      print(result);
      //httpclient关闭
      httpClient.close();
    } catch (e) {
      print("请求失败$e");
    } finally {
      print("------------------------------------");
    }
  }

异步操作
Dart是单线程模型,也就没有了所谓的主线程/子线程之分。
Dart也是Event-Looper以及Event-Queue的模型,所有的事件都是通过EventLooper的依次执行。
而Dart的Event Loop就是:
从EventQueue中获取Event
处理Event(用户输入,点击,Timer,文件IO)
直到EventQueue为空
单线程模型:
一旦某个Dart的函数开始执行,它将执行到这个函数结束,也就是Dart的函数不会被其他Dart代码打断。
Dart中没有线程的概念,只有isolate,每个isolate都是隔离的,并不会共享内存。而一个Dart程序是在Main isolate的main函数开始,而在Main函数结束后,Main isolate线程开始一个一个(one by one)的开始处理Event Queue中的每一个Event。
dart库提供asynchronous功能,该功能提供接口来进行好费时间的操作,比如文件读写。网络请求,该功能返回Future或Steam对象。
以上引用 None_Ling简书内容

Dart与JavaScript一样,是一个单线程模型。但这并不意味着Dart中不能进行异步编程,
只是这种异步编程区别于传统的多线程异步方式。
Dart中的所有代码都只在一个线程上运行,但Dart代码可以运行在多个isolate上。
isolate可以看做一个微小的线程,isolate由虚拟机调度,isolate之间没有共享内存,因此它们之间没有竞争,
不需要锁,不用担心死锁,因此开销小,性能高。由于没有共享内存,所以它们之间唯一的通信只能通过Port进行,
而且Dart中的消息传递也总是异步的。

方式:
1.使用async函数和await表达式
2.使用Future功能提供的api
如何获取返回结果
a.使用async和一个异步的循环(await for)
b.使用Stream的相关api
Dart库充满了返回Future或Stream对象的函数。这些函数是异步的:它们在设置一个可能耗时的操作(如I / O )后返回,而无需等待该操作完成
虽然异步函数可能会执行耗时的操作,但它不会等待这些操作。相反,异步函数只在遇到它的第一个await表达式之前执行。然后,它返回一个Future的对象,只有在await表达式完成后,才恢复执行。
示例:
Dart语言入门介绍_第10张图片
关于Stream异步支持移步此处
两篇写的很好的博客
上篇
下篇

你可能感兴趣的:(Flutter)