函数

无返回值的函数

1
2
3
4
5
6
7
8
void customFunction(){
print('custom function!');
}

void main(){

customFunction()
}

有返回值的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 返回 int 类型的 函数
int customFunctionNum(){
var num = 101;
return num;
}

String customFunctionStr(){
var str = 'this is string!';
return str;
}

List customFunctionList(){
var arr = ['张三','李四'];
return arr;
}

Map customFunctionMap(){
var person = {
"name": "张三"
};
return person;
}

void main(){
var num = customFunctionNum()
print(num) // 101
var myStr = customFunctionStr()
print(myStr) // this is string!
var myList = customFunctionList()
print(myList) // ['张三', '李四']
var myMap = customFunctionMap()
print(myMap) // {name: '张三'}
}

函数作用域

1
2
3
4
5
6
7
8
9
10
11
12
// 全局作用域
void test(){
// 局部作用域 外部无法直接访问!
void internalFun(){
print('internalFun function!');
}
internalFun()
}
void main(){
// internalFun() 无法调用
test();
}

匿名函数

没有名字的函数,将函数赋值与一个变量!

1
2
3
4
5
6
7
8
var anonymousFunction = (){
print('anonymousFunction function!');
}

void main(){

anonymousFunction()
}

箭头函数

1
2
3
var arr = [1,3,4,5,6]
arr.map((item) => item*=2)

自执行函数

1
2
3
((int n){
print('立即执行函数!');
})(12);

闭包

全局变量: 常驻内存,容易污染全局!
局部变量: 不会常驻内存,会被垃圾回收,不会污染全局!
闭包: 函数嵌套函数,内部函数会调用外部函数的变量或参数!

1
2
3
4
5
6
7
8
9
10
11
12
fun(){
var num = 12;
return (){
num++;
}
}
void main(){
var bfun = fun();
// 这里的函数就是 return 出去的函数!
bfun(); //13
bfun(); //14
}

参数

定义参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// int num  限制传参的类型!
int sumNum(int num){
int result = 0;
for( var i = 0; i < num; i++ ) {
result+=i;
}
return result;
}

// 多个参数
String printUserInfo(String name, int age) {
<!-- print('I am $name - $age'); -->
return 'I am $name - $age';
}

void main(){
// 单个参数
var result = sumNum(15);
print(result)

// 多个参数
var userInfo = printUserInfo('张三', 15);
print(userInfo)
}

(可选 or 默认)参数

可选参数可用 [int age, ...]来表示!
默认参数可用 (String name = '张三')来表示!

1
2
3
4
5
6
7
8
9
10
11
12
String printUserInfo(String name, [ String sex = '男', int age ]) {
print('I am $name - $age');
if ( age != null ) {
return 'I am $name - $sex - $age'
}
return 'I am $name - $sex';
}
void main(){
// 多个参数
var userInfo = printUserInfo('张三','女', 15);
print(userInfo);
}

命名参数

命名参数使用{ int age, ... }定义!

1
2
3
4
5
6
7
8
9
10
11
12
String printUserInfo(String name, {int age , String sex = '男'}) {
print('I am $name - $age');
if ( age != null ) {
return 'I am $name - $sex - $age'
}
return 'I am $name - $sex';
}
void main(){
// 多个参数
var userInfo = printUserInfo('张三', age: 15, sex: '女');
print(userInfo);
}

类是对象的抽象,是具体实体的一种描述!
比如 有一个人叫做张三,他的年龄是18,性别是;
以下通过类的形式来描述下这个人的特征:

创建一个类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

// 创建一个类
class Person{
String name = '张三';
int age = 18;
String sex = '男'

getPerson(){
return '${this.name} - ${this.age}'
}

setAge(int age){
this.age = age;
}
}

void main(){

// 将类实例化一个对象
var person = new Person();
//or
// Person person = new Person();
//调用类中的属性
print(person.name)

// 调用类中的方法
var personInfo = person.getPerson();
print(personInfo)

// 给类中的属性设置 值
person.setAge(28)
print(person.age)
}

构造函数

ClassName(…) //普通构造函数
Classname.identifier(…) //命名构造函数
const ClassName(…) //常量构造函数
factroy ClassName(…) //工厂构造函数

Dart 构造函数不允许重载,即不允许有相同名称的构造函数,否则编译器会报错

默认构造函数

构造函数 在实例化的时候 触发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 创建一个类
class Person{
String name = '张三';
int age = 18;
String sex = '男'

Person(){
print('这里是无参构造函数!');
}

/* Person(String name. int age, String sex){
this.name = name;
this.age = age;
this.sex = sex;
print('这里是有参构造函数!');
}*/

// 简写方式 ↑ 含义同上注释代码
Person(this.name,this.age,this.sex)

getPerson(){
return '${this.name} - ${this.age}'
}

setAge(int age){
this.age = age;
}
}

void main(){
// 这里实例化的时候,构造函数便会执行!
Person p1 = new Person() // 无参构造

Person p2 = new Person('王五',16,'女') // 无参构造
}

命名构造函数

可以定义多个命名构造函数!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 创建一个类
class Person{
String name = '张三';
int age = 18;
String sex = '男'

Person.eat(){
print('命名构造函数!');

}
Person.play(){
print('命名构造函数!');
}
}

void main(){
var p1 = new Person.eat();
var p2 = new Person.play();
}

引入其他文件下的类

通过import方式引入其他文件下的类!

1
2
3
4
5
import './lib/Person.dart';

void main(){
var p1 = new Person.eat();
}

类中定义私有属性和方法

定义私有属性只需要在属性前面加 '_'下划线即可,前提,该类是单独文件存放

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// lib/Person.dart
class Person{
String name = '张三';
int age = 18;
String _sex = '男' //私有属性

Person.eat(){
print('命名构造函数!');

}
Person.play(){
print('命名构造函数!');
}

void _run(){
print('私有方法!');
}

}

import './lib/Person.dart';

void main(){
var p1 = new Person();
print(p1._sex) //访问不到
print(p1._run()) //访问不到

print(p1.name) // 张三
}

get 和 set 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Person{
String name = '张三';
int age = 18;
String _sex = '男' //私有属性

get newAge{
return this.age+1;
}

set setAge(value){
this.age = value;
}
}

void main(){
var p1 = new Person();
print(p1.newAge); // get
p1.setAge = 19; // set
}

构造函数 设置属性默认值

实例化之前会先执行下赋值!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Person{
String name = '张三';
int age = 18;
String _sex = '男' //私有属性

// 赋值
Person({this.name = "王五", this.age = 19}){
print('我在实例化之前先做了一次初始化操作 $name $age!')
}
}

void main(){
var p1 = new Person();
}

静态属性 和 静态方法

非静态方法 可以访问静态成员以及非静态成员!
静态方法 可以访问静态成员, 但是不可以访问非静态成员!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class Person{
// 静态属性
static String name = '张三';

int age = 18;
String _sex = '男' //私有属性

// 静态方法
static void getInfo(){
print('我是静态方法!')
}

// 非静态方法
void show(){
// 调用静态属性
print(name)

// 调用非静态属性
print(this.age)

// 调用静态方法
getInfo()
}

// 赋值
Person():name = "王五", age = 19{

}
}

void main(){
// 实例化对象
var p1 = new Person();

//调用非静态属性 需要通过实例化对象
print(p1.age)

// 调用静态属性 name
print(Person.name)

// 调用静态方法
Person.getInfo()
}

静态属性可以`不需要实例化对象后`调用`属性` 和 `方法`

对象操作符

操作符描述
?条件运算符
as类型转换
is类型判断
..级联操作

? 操作符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Person{
String name = '张三';
int age = 18;
String _sex = '男' //私有属性

// 赋值
void showInfo(){

}
}

void main(){
var p1 = new Person();

p1?.showInfo()
}

p1?.showInfo() p1对象若存在则调用该方法,若不存在则不调用!

as 操作符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Person{
String name = '张三';
int age = 18;
String _sex = '男' //私有属性

// 赋值
void showInfo(){

}
}

void main(){
var p1 = '';
p1 = new Person();

// 将字符串类型 转换为 Person
(p1 as Person).showInfo();
}

is 操作符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Person{
String name = '张三';
int age = 18;
String _sex = '男' //私有属性

// 赋值
void showInfo(){

}
}

void main(){
var p1 = new Person();

// 判断 p1 是不是 Person对象!
print(p1 is Person); // true

print(p1 is Object); // true

}

.. 连缀操作符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Person{
String name = '张三';
int age = 18;
String _sex = '男' //私有属性

// 赋值
void showInfo(){
print('$name $age $_sex');
}
}

void main(){
var p1 = new Person();
// 一般操作!
p1.showInfo();
p1.name = '王五';
p1.age = 29;
p1.showInfo();

// 使用 .. 操作符
p1..name = '王五'
..age = 18
..showInfo();
}

继承

1、子类使用 extends关键词来继承父类!
2、子类会继承父类的属性和方法,但不会继承构造函数!
3、子类能复写父类的方法 gettersetter;

父类的构造函数是无法被继承的!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class Person{
String name;
int age;
String sex;

Person(this.name, this.age,this.sex);

// 命名构造参数
Person.setAge(this.name,this.age,this.sex);

void getPersonInfo(){
print('${this.name}, ${this.age}, ${this.sex}');
}
void setPerson(int age){
this.age = age;
}
}


class Web extends Person{
int? phone;
double? height;
// 这里 Web 子类 接收到构造参数后 通过 super形式 来接受子类中的构造参数传递给父类!
// Web(String name, int age, String sex, int phone, double height) : super(name, age, sex) {
// this.phone = phone;
// this.height = height;
// }
// 只允许有一个 Web() 构造
// Web(String name, int age, String sex, this.phone, this.height): super(name, age, sex);
// 父类命名构造函数
Web(String name, int age, String sex, int phone, double height) : super.setAge(name, age, sex) {
this.phone = phone;
this.height = height;
}
// 子类的方法
void getPhone(){
print('$phone');
// 子类中调用父类的方法
super.getPersonInfo();
}
// 复写 父类的方法
@override // 可以写可以不写 `override`
void setPerson(int age){
this.age = age;
print('override age $age');
}
}

void main(){
var p1 = new Web('张三', 18, '男', 1524232132, 182.0);
// 调用父类方法
// p1.getPersonInfo();

// 调用子类方法
// p1.getPhone();

p1.setPerson(19);
}

抽象类

抽象类 在dart中 用于定义标准!继承抽象类的 子类 需要按照抽象类中定义的去实现!
定义抽象类的关键字 abstract!
抽象方法 没有方法体的方法为抽象方法!
子类继承抽象类必须实现抽象类中的抽象方法!
抽象类不能被实例化,只有继承它的子类可以实例化!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
abstract class Animal{
eat(); //抽象方法

void getAnimalInfo(){ // 非抽象方法

};
}

class Dog extends Animal{
@override
eat(){
print('小狗');
}

run(){}; //子类特有的方法
}

class Cat extends Animal{
@override
eat(){
print('小猫');
}

run(){}; //子类特有的方法
}
void main(){
// 多态
var dog = new Dog();
dog.eat();

// 多态
var cat = new Dog();
cat.eat();
}

多态

子类的实例化指向父类! 或者 子类继承去实现父类,每个子类调用父类的同一个方法,展现出多种结果,便可称为多态!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void main(){
// 多态
var dog = new Dog();
dog.eat();

// 多态
var cat = new Dog();
cat.eat();

// 将子类 指向 父类
Animal dog = new Dog();
// dog.run(); 指向父类后 无法 调用子类自身特定的方法!
dog.eat();
}

red 子类指向父类后 无法 调用子类自身特定的方法!

接口

dart中没有interface关键字,所以定义接口的时候,只是普通类 or 抽象类,通过 implements关键字来实现接口!
接口是一种标准 ,是一种规范,它可以约束子类必须按照接口的方式去实现接口中的 方法属性!
实现接口的子类,必须实现接口中所定义的 属性抽象方法!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// 定义普通的 db 接口
class Db{
String uri;
add(String data);
edit();
delete();
get();
}
//这两种方式 都可以通过 implements 关键字 来实现!
// 顶一个 抽象接口
/*abstract class Db{
String uri;
add(String data);
edit();
delete();
get();
}*/
// 实现 DB 接口
class Mysql implements Db{
@override
String uri;

Mysql(this.uri);

@override
add(String data){
print('mysql add data $data!');
}

@override
edit(String data){}

@override
delete(String data){}

@override
get(String data){}
}

void main(){
var mysql = new Mysql('http:xxxxxx:8080');

mysql.add('5923237821372');
}

抽象类 and 接口的区别:
abstract: 在子类继承抽象类时 [需要用到父类中的特定方法],这时候需要用到 [extends] 了!
implements: 若子类只是为了 [实现父类的约束方法],那么可以通过 [implements] 来实现

一个类实现多个接口

一个类实现多个接口,可以通过 implements A, B 这种以逗号分隔来实现!
需要实现多个接口中的约定方法属性 !

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
abstract class A{
printInfoA();
}

abstract class B{
printInfoB();
}

class C implements A, B{
@override
printInfoA(){}

@override
printInfoB(){}
}

mixins 混入

dart中 没有 多继承, 但是可以实现多个接口!
mixins 混入 是将 多个 类 通过 关键字 with 混入到一个新的类里,这样就可以同时有多个类下的方法调用了!
注意:
1、mixins 对应的 类 内 不允许有构造函数!
2、mixins 对应的 类 不允许继承其他类!
3、一个类 可以 mixins 多个 mixins类!
4、一个类 [可以继承另一个类] ,并还可以 [混入多个其他普通类]! 继承的类可以有构造函数!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Person{
printInfoPerson(){
print('Person');
};
}
class A{
printInfoA(){
print('A');
};
}

class B{
printInfoB(){
print('B');
};
}
// 将 A 和 B 混入到 C 类中
class C extends Person with A, B{

}
// or
/*class C with A, B{

}*/
main(){
var c = new C();

c.printInfoA();

c.printInfoB();

print(c is A); // true

print(c is B); // true

print(c is C); // true
}

如果混入的类中出现了, 重复的方法或者属性,那么,后面的会把前面的覆盖掉!

泛型

针对,类型的不确定性而存在的!
比如一个方法返回的 类型 String、int 、或者 bool等!
减少代码的复用!

泛型方法

普通写法

1
2
3
4
5
6
7
8
9
10
11
12
String getData(String val){
return val;
}
int getData2(int val){
return val;
}

main(){
getData('123123');

getData2(112412);
}

使用泛型

1
2
3
4
5
6
7
8
9
getData<T>(T val){
return val;
}

main(){
getData<String>('123123');

getData<int>(112412);
}

泛型类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Mylist<T>{
var arr = <T>[];
List list = <T>[];
void add(T val){
list.add(val);
}
List getList(){
return list;
}
}
main(){
// 任意类型
var myList = new Mylist();
myList.add('12312');
myList.add(123123);
myList.add(true);
var newList = myList.getList();
print(newList);

// 指定 String 类型
var myList2 = new Mylist<String>();
myList2.add('dwadasd');
myList2.add('sdadsad');
}

泛型接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// 定义一个缓存接口
abstract class Cache<T>{
String? key;
T? value;
getKey(String Key);
setKey(String Key, T value);
}

// 定义一个文件缓存类
class FileCache<T> extends Cache<T>{
@override
getKey( String key ){
return key;
}
@override
setKey( String key, T value ){
print('set key $key $value');
}
}
// 定义一个内存缓存类
class MemoryCache<T> implements Cache<T>{
@override
String? key;

@override
T? value;

@override
getKey( String key ){
return '$key ${this.key} ${this.value}';
}

@override
setKey( String key, T value ){
this.key = key;
this.value = value;
}
}

main(){
// 抽象类
// 不限制类型
FileCache fileCache = new FileCache();
fileCache.setKey('name', '张三');

// 限制类型
FileCache fileCache2 = new FileCache<int>();
fileCache2.setKey('name', 123);

// 接口
MemoryCache memoryCache = new MemoryCache();
memoryCache.setKey('name', '张三');
var myCache = memoryCache.getKey('name');
print('memoryCache $myCache');
}

dart中的库

自定义库

所谓的自定义库 就是将 一个功能单独封装成一个文件.dart,在需要的地方通过import './lib/xxx.dart'方式引入!

red

1
2
3
4
5
6
7
8
9
10
11
class Animal{
String? name;
String? sex;
String? age;

Animal(this.name,this.sex,this.age);

String getAnimalInfo(){
return 'Animal ${this.name}-${this.sex}-${this.age}!'
}
}

red

1
2
3
4
5
6
7
8
9
10
11
12
import './lib/animal.dart';
// 只引入部分功能
// import './lib/animal.dart' show getAnimalInfo;
// 隐藏指定功能 [隐藏后就无法使用了]
// import './lib/animal.dart' hide getAnimalInfo;
main(){
var animal = new Animal('豆豆', '母', '8个月');

var animalInfo = animal.getAnimalInfo();

print('animalInfo $animalInfo');
}

show:

用来指定部分功能可用!


hide:

用来指定部分功能不可用!

系统库

math

提供一些有关数学计算的一个库!

1
2
3
4
5
6
7
import 'dart:math';

main(){
print(min(12, 20)); // 12 最小值

print(max(12, 20)); // 20 最大值
}

io 和 convert

这两个库 可以处理下 接口 请求什么的!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import 'dart:io';
import 'dart:convert';

getFormDataByApi() async{
// 创建 httpClient
var httpClient = new HttpClient();
// 创建 url对象
var uri = Uri.http('news-at.zhihu.com','/api/3/stories/latest');
// 发起请求
var request = await httpClient.getUrl(uri);
// 关闭请求等待响应
var response = await request.close();
//解码响应的内容
return await response.transform(utf8.decoder).join();
}

main() async{
var result = await getFormDataByApi();
print(result);
}

asyncawait
async 让代码块变为 异步代码块!
await 让当前代码 作用域同步状态下,等执行完当前这一步,在执行下一步!

第三方库

搜索资源库

创建pubspec.yaml文件

这个文件 类似与 packge.json文件,项目和依赖包管理文件!

文件内容如下:

1
2
3
4
name: project_name
description: project_desc
dependencies:
http: ^0.13.5

dependencies,下的依赖版本,可以从第三方包地址下提供的版本获取即可!

运行 pub get获取远程仓库

1
pub get

引入库[第三方库提供的案例]

as 定义别名, 有效的防止 库的名字重复问题!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import 'dart:convert' as convert;

import 'package:http/http.dart' as http;

void main(List<String> arguments) async {
// This example uses the Google Books API to search for books about http.
// https://developers.google.com/books/docs/overview
var url =
Uri.https('www.googleapis.com', '/books/v1/volumes', {'q': '{http}'});

// Await the http get response, then decode the json-formatted response.
var response = await http.get(url);
if (response.statusCode == 200) {
var jsonResponse =
convert.jsonDecode(response.body) as Map<String, dynamic>;
var itemCount = jsonResponse['totalItems'];
print('Number of books about http: $itemCount.');
} else {
print('Request failed with status: ${response.statusCode}.');
}
}

其他安装方式

1
dart pub add http

or

1
flutter pub add http

2.13版本新特性

? 可控类型

null safety 空安全

1
2
3
4
5
int a = 123;
a = null; // 不允许

String b = '123';
b = null; //不允许

若想可空类型的话需要通过 ?来表示

1
2
3
4
5
6
7
8
9
String? a = '123';
a = null;// 允许 可控类型

int? a = 123;
b = null; // 允许 可控类型

List<String>? list = ['123','123'];
list = null; // 允许 可控类型

方法的使用

1
2
3
4
5
6
7
// 方法 返回空类型
String? getName(String name){
if( name != null ) {
return name;
}
return null;
}

!类型断言

1
2
3
String> str = 'i am tom!'
str = null;
print(str.length);

print(str.length); 如果这样写,编译会报错,因为str可能会为空,导致length属性取不到问题!
那我们这样写

1
2
3
4
5
6
7
8
String> str = 'i am tom!'
str = null;
print(str!.length);

// 一般用在方法里
void getName(String? str){
print(str!.length);
}

print(str!.length); 这样的话,! 作用 会先判断值是否不为空,不为空的情况下打印长度,否则会抛出异常!

late 关键字

可以在定义 类中延迟初始化属性!, 防止 属性 初始化不赋值的情况下,编译报错问题!

1
2
3
4
5
6
7
8
9
10
class Person{
late String name; // 这里如果没有 late 关键字的话,编译会报错!
late String sex;

void setPerson(String name, String sex){
this.name = name;
this.sex = sex;
}
}

required 关键字

可以使参数不为空!
主要用于允许根据需要标记任何命名参数(函数或类),使得它们不为空。因为可选参数中必须有个 required!

1
2
3
4
5
6
7
8
// 有默认值的话 可以不需要加 required
String printInfo(String userName, { int age=20, String sex = '男' }){

}

String printInfo(String userName, { required int age, required String sex }){

}

在类中使用

1
2
3
4
5
class Person{
String name;

Person({ required this.name });
}

可为空的可选参数选项 ?

1
2
3
4
5
6
7
8
9
10
class Person{
int age;
String? name;

Person({ this.name, required this.age });
}

void main(){
var p1 = new Person(age: 18);
}

性能优化之常量

final 常量

可先声明,后赋值,只能赋值一次;
声明的常量允许在声明后在赋值,赋值后不可改变,final 声明的变量是在运行时确定的!

1
2
3
4
final a; // 声明
a = 14; // 只允许 赋值一次
a = 13; // 不允许 会报错
print('$a');

const 常量

声明的常量是在编译的时候确认的,永远不会改变!
声明一个常量 并 赋值;
identical(a,b) 方法 用来判断两个对象是否指向一个存储空间!

1
const a = 12;
1
2
3
4
5
6
7
var o1 = new Object();

var o2 = new Object();

print(identical(o1,o2)); //false

print(identical(o1,o1)); //true

print(identical(o1,o2)); //false 这时候 两个空间地址不一样!
使用 const 来声明构造函数

1
2
3
4
5
6
7
8
9
var o1 = const Object();

var o2 = const Object();

print(identical(o1,o2)); //true

print(identical([2],[2])); //false

print(identical(const [2],const [2])); //true

identical(o1,o2) // true 这时候 两个对象公用了同一个空间地址!

注意:

const关键词在多个地方创建相同的对象的时候,内存中只保留了一个对象!


创建的对象 两个值如果一样的话就会共享一个存储空间!

常量构造函数

1、常量构造函数需要以const关键字修饰!
2、const 构造函数必须成员变量都是final的类!
3、如果实例化不加const修饰符,即使调用的是常量构造函数,实例化对象也不是常量实例化对象!
4、flutter 中 const 修饰符不仅仅是节省组件构建时的内存开销,Flutter在需要重新构建组件的时候,是不会重新构建 const组件!
5、实例化常量构造函数的时候,多个地方创建这个对象,如果传入的值相同,只会保留一个对象!

1
2
3
4
5
6
7
8
9
10
11
12
13
// 常量构造函数
class Container{
final int width;
final int height;
const Container({required this.width, required this.height});
}

void main(){
var c1 = const Container({width: 154,height 102});
var c2 = const Container({width: 154,height 102});

print(identical(c1, c2)) // true
}

var c1 = const Container({width: 154,height 102})

const 修饰的构造函数,一定时常量构造函数!

共享存储空间条件:

1、常量 2、值相等!