函数 无返回值的函数 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 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 ) var myStr = customFunctionStr() print (myStr) var myList = customFunctionList() print (myList) var myMap = customFunctionMap() print (myMap) }
函数作用域 1 2 3 4 5 6 7 8 9 10 11 12 void test(){ void internalFun(){ print ('internalFun function!' ); } internalFun() } void main(){ 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(); bfun(); bfun(); }
参数 定义参数 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 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(); 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(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 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); p1.setAge = 19 ; }
构造函数 设置属性默认值 实例化之前会先执行下赋值!
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) 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(); (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(); print (p1 is Person); print (p1 is Object ); }
.. 连缀操作符 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、子类能复写父类的方法 getter 和 setter;
父类的构造函数是无法被继承的!
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(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 void setPerson(int age){ this .age = age; print ('override age $age ' ); } } void main(){ var p1 = new Web('张三' , 18 , '男' , 1524232132 , 182.0 ); 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.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 class Db { String uri; add(String data); edit(); delete(); get (); } 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' ); }; } class C extends Person with A , B {} main(){ var c = new C(); c.printInfoA(); c.printInfoB(); print (c is A); print (c is B); print (c is C); }
如果混入的类中出现了, 重复的方法或者属性,那么,后面的会把前面的覆盖掉!
泛型 针对,类型的不确定性而存在的! 比如一个方法返回的 类型 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); 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' ;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 )); print (max(12 , 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 { var httpClient = new HttpClient(); 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); }
async 和 awaitasync 让代码块变为 异步代码块!await 让当前代码 作用域同步状态下,等执行完当前这一步,在执行下一步!
第三方库 搜索资源库 引用站外地址
创建pubspec.yaml文件 这个文件 类似与 packge.json文件,项目和依赖包管理文件!
文件内容如下:
1 2 3 4 name: project_name description: project_desc dependencies: http: ^0.13.5
dependencies,下的依赖版本,可以从第三方包地址下提供的版本获取即可!
运行 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 { var url = Uri .https('www.googleapis.com' , '/books/v1/volumes' , {'q' : '{http}' }); 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} .' ); } }
其他安装方式 or
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 String sex; void setPerson(String name, String sex){ this .name = name; this .sex = sex; } }
required 关键字可以使参数不为空! 主要用于允许根据需要标记任何命名参数(函数或类),使得它们不为空。因为可选参数中必须有个 required!
1 2 3 4 5 6 7 8 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 2 3 4 5 6 7 var o1 = new Object ();var o2 = new Object ();print (identical(o1,o2)); print (identical(o1,o1));
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)); print (identical([2 ],[2 ])); print (identical(const [2 ],const [2 ]));
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)) }
var c1 = const Container({width: 154,height 102})
const 修饰的构造函数,一定时常量构造函数!
共享存储空间条件:
1、常量 2、值相等!