变量
变量的声明
var——没有初始值,可以变成任何类型。有初始值,类型被锁定
var data=123;
data='123';//不可,编译器直接报错
dynamic——动态任意类型,编译时不会检查
dynamic data2=123;
data2='123';//不会报错
object——动态任意类型,编译时会检查
object data2=123;
data2='123';//不会报错
变量默认值
一切皆对象,默认值都为null
没有初始化的变量默认为null
final和const
声明的类型可以省略
final (String 省略) str='123'
const (String 省略) str='123'
初始化后不能再赋值
不能和var同时使用
类级别常量,使用static const
const可以用其它const常量来初始化值
const a=1;
const b=2;
const sum=a*b;
使用const赋值声明,const可以省略
const list=const [];
const list=[];//也可
可以改非final、非const变量值,即使曾经是const值
var list1= const [1,2,3];
const list2= const [1,2,3];
fial list3= const [1,2,3];
list1=[1];
list2=[2];//编译器直接报错
list3=[3];//编译器直接报错
const导致的不可变性,是可以传递的
final List ls=[1,2,3];
ls[1]=0;//正确可以修改
const List ls=[1,2,3];
ls[1]=0;//编译后报错,不可以修改
const的不可变性传递给了它的子元素
相同的const常量不会在内存中重复创建
final List ls=[1,2,3];
final List ls2=[1,2,3];
//打印后不相等两内存不同
const List ls=[1,2,3];
const List ls2=[1,2,3];
//打印后不相等两内存相同
const需要是编译时常量
final fl=DateTIme.now();
const fl=DateTIme.now();//编译后报错
//DateTime.now是运行时才能确定的常量,但const要求的是编译前就能确定
内置类型
Numbers
int:整数值
double:64bit双精度浮点
int和double是num的子类
Strings
可以用单引号或双引号创建字符串
String a="111" "222" "333";//拼接也可以这么写,不会出错
String b='''abc
def
ghi
''';
打印后输出
abc
def
ghi
可以用三个单引号或双引号创建多行的字符串
String b='''abc\ndef
ghi
''';
打印后输出
abc
def
ghi
r表示raw字符串
String b=r'''abc\ndef
ghi
''';
打印后输出
abc\ndef
ghi
级联符
StringBuffer sb=StringBuffer();
sb.write('abc');
sb.write('def');
sb.write('ghi');
可以写成
sb..write('abc')..write('def')..write('ghi')..writeAll(['a','b','c']);
..表示集连符,链式调用
Booleans
bool对象未初始化则是null
Lists
Dart中可以直接打印list包括list的元素
支持泛型
有增删改查,支持倒序,自带排序,洗牌,可以使用+将两个list合并
Sets
set1.difference;
set1.difference(set2);返回set1集合里面有但是set2里面没有的
Set set1=Set();
Set set2=Set();
set1.addAll([1,2,3,4]);
set2.addAll([1,2,5,6]);
var difference=set1.difference(set2);
print(difference);
打印输出
{3,4}
set1.intersection
set1.intersection(set2);返回set1和set2的交集
set1.union(set2)
set1.union(set2);返回set1和set2的并集
set1.retainAll
set1.retainAll();把只保留某些元素(要保留的元素在原set中存在)。把set1变成了交集
Set set1 = Set();
set1.addAll([1,2,3]);
Set set2 = Set();
set2.addAll([1,5,6]);
set1.retainAll(set2);
打印set1得到
{1}
intersection和retainAll的区别:
intersection返回交集
retainAll把set1变成交集
Maps
Runes–符号字符
Runes runes = new Runes('\u6211');
var str1 = String.fromCharCodes(runes);
print(str1);
打印得到
我
Symbols–标识符
有关反射,已被移除了
函数
定义
可以在函数内定义
定义函数可以省略类型,所有函数都有一个返回值,没有指定,则返回值则默认 return null;
int add(int a,int b){
return a+b;
}
对于只有一个表达式的方法,可以用=>表达式来定义
int add(int a,int b) => a+b;
可选参数
可选命名参数。使用 {param1, param2, …} 的形式来指定命名参数。
int add({int a,int b}) => a+b;
print(add());
print(add(a:1));
print(add(b:1));
print(add(a:1,b:1));
可选位置参数
int add2(int a, [int b, int c]) => a+b;
print(add2(1));
print(add2(1,2));
print(add2(1,2,2));//输出3
以上有些会报错是因为a或b为null了
int+null不能转为int,会报错
默认值
可选位置默认值。曾经有用:的,现在建议用等号
int add2(int a , [int b=2, int c=2]) => a+b;
int add2(int a , {int b=2, int c=2}) => a+b;
可使用list或map作为默认值,但必须是const。
int add2({List list=const[1,23]}) {
}
匿名函数
无参匿名
var a=()=>print('123');
有参匿名
var a=(name)=>print('${name}');
可在其他函数中直接调用或传递给其他函数
List test(List list, String func(str)) {
for (var i = 0; i < list.length; i++) {
list[i] = func(list[i]);
}
return list;
}
var ls = ['aaa', 'bbb', 'vvv'];
print(test(ls, (str) => str * 2));
打印得
['aaaaaa','bbbbbb','vvvvvv'];
闭包
Function makeAddFunc(int x) {
x++;
return (int y) => x + y;
}
var addFun2 = makeAddFunc(2);
var addFun4 = makeAddFunc(4);
print(addFun2(2));//输出5
print(addFun4(3));//输出8
函数别名
typedef不能写在函数里面
typedef MyFunc(int a, int b);
void main() {
add(int a, int b) {
print('${a+b}');
}
divide(int a, int b) {
print('${a/b}');
}
MyFunc myFunc=add(1, 2);//得到3
myFunc=divide(20, 5);//得到4.0
calcuter(int a, int b, MyFunc func) {
func(a, b);
}
calcuter(8, 10, add);//得到18
操作符
后缀操作
String s;
print(s?.length);
print(s != null ? s.length : '');//Java中判空写法
前缀操作
print(1 / 2);//输出0.5
print(4 / 2);//输出2.0
print(1 ~/ 2);//输出0 先1/2,然后去掉小数点
print(4 / 2);//输出2
类型操作
num n = 1;
num n1 = 1.0;
//as 类型转换
int i = n as int;
print(i);
//is判断类型
print(n is double);
print(n is! double);
判断是否为空
java中:表达式?条件1:条件2;表达式true返回条件1,false返回条件2;
dart中:条件1??条件2;??左边非空则返回左边结果,否则返回右边
级联
..
赋值
??=左边为null,则右边赋值给左边,否则保持不变
bool gg=true;
gg??=false;
print(gg);//输出true
运算符重载
重载+
重载-
class Parent {
final int x;
final int y;
const Parent(this.x, this.y);
//重载+
Parent operator +(Parent w) {
return Parent(x + w.x, y + w.y);
}
//重载-
Parent operator -(Parent w) {
return Parent(x - w.x, y - w.y);
}
}
void main() {
final w1 = Parent(2, 3);
final w2 = Parent(3, 4);
final sum1 = w1 + w2;
final sum2 = w1 - w2;
print([sum1.x, sum1.y]);
print([sum2.x, sum2.y]);
}
异常
Exception类型
Error类型
抛出
//抛出Exception对象
throw new FormatException('格式化异常');
//抛出Error对象
throw new OutOfMemoryError();
//抛出任意非null对象
throw '这是一个异常'
捕获
使用 on 来指定异常类型,使用 catch 来 捕获异常对象。
try {
throw new OutOfMemoryError();
} on OutOfMemoryError {
print('没有内存了');
} on Error catch(e) {//指定对象类型
print('Unknown error: $e');
} catch (e, s) {
print('Exception details: $e');//异常对象
print('Stack Trace: $s');//堆栈信息
} finally {
print('end');
}
类
构造函数
命名构造函数
重定向构造函数
Java中
class Point {
num x;
num y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
}
Dart中
class Point {
num x;
num y;
//构造函数
Point(this.x, this.y);
//命名构造函数,相当于是取了别名
Point.fromJson(Map json) {
x = json['x'];
y = json['y'];
}
//重定向构造函数,使用冒号调用其他构造函数
Point.alongXAxis(num x) : this(x, 0);
}
初始化列表
import 'dart:math';
class Point {
//final变量不能被修改,必须被构造函数初始化
final num x;
final num y;
final num distanceFromOrigin;
//初始化列表
Point(x, y)
: x = x,
y = y,
distanceFromOrigin = sqrt(x * x + y * y);
}
超类构造函数
class Parent {
int x;
int y;
//父类命名构造函数不会传递
Parent.fromJson(x, y)
: x = x,
y = y {
print('父类命名构造函数');
}
}
class Child extends Parent {
int x;
int y;
//重定向
//若超类没有默认构造函数, 需要手动调用超类其他构造函数
Child(x, y) : super.fromJson(x, y) {
//调用父类构造函数的参数无法访问 this
print('子类构造函数');
}
//在构造函数的初始化列表中使用super(),需要把它放到最后
Child.fromJson(x, y)
: x = x,
y = y,
super.fromJson(x, y) {
print('子类命名构造函数');
}
}
常量构造函数
class Point {
//定义const构造函数必须保证变量都是final
final num x;
final num y;
const Point(this.x, this.y);
}
工厂构造函数
class Singleton {
String name;
//工厂构造函数无法访问this,所以这里用static
static Singleton _singleton;
//工厂函数不会自动生成实例
factory Singleton([String name = 'singleton']) {
return Singleton._singleton ??= Singleton._newObject(name);
}
//匿名构造函数,省略方法体
// Singleton._newObject(name){
// this.name=name
// }
Singleton._newObject(this.name);
}
setter和getter
class Recttangle {
num top;
num left;
num width;
num height;
Recttangle(this.top, this.left, this.height, this.width);
// num get right => left + width;
num get right {
return left + width;
}
//set right(num value) => left = value - width
set right(value) {
left = value - width;
}
num get bottom {
return top + height;
}
set bottom(value) {
top = value - height;
}
}
抽象类
abstract修饰class
不能被是实例化,除非定义一个工厂构造函数
工厂模式
abstract class Foods {
//工厂模式
factory Foods(String type) {
if (type == 'friuts') {
return FriutsMessage();
} else if (type == 'vegetables') {
return VegetablesMessage();
} else {
return SnacksMessage();
}
}
void doEat();
}
class FriutsMessage implements Foods {
@override
void doEat() {
print('水果');
}
}
class VegetablesMessage implements Foods {
@override
void doEat() {
print('蔬菜');
}
}
class SnacksMessage implements Foods {
@override
void doEat() {
print('零食');
}
}
void main() {
FriutsMessage friutsMessage = FriutsMessage();
friutsMessage.doEat();
VegetablesMessage vegetablesMessage = VegetablesMessage();
vegetablesMessage.doEat();
SnacksMessage snacksMessage = SnacksMessage();
snacksMessage.doEat();
}
顶级函数
//顶级函数
Foods foodsFactory(String type) {
if (type == 'friuts') {
return FriutsMessage();
} else if (type == 'vegetables') {
return VegetablesMessage();
} else {
return SnacksMessage();
}
}
class FriutsMessage extends Foods {
@override
void doEat() {
print('水果');
}
}
class VegetablesMessage extends Foods {
@override
void doEat() {
print('蔬菜');
}
}
class SnacksMessage extends Foods {
@override
void doEat() {
print('零食');
}
}
void main() {
FriutsMessage friutsMessage = FriutsMessage();
friutsMessage.doEat();
VegetablesMessage vegetablesMessage = VegetablesMessage();
vegetablesMessage.doEat();
SnacksMessage snacksMessage = SnacksMessage();
snacksMessage.doEat();
}
可调用类
class ClassFunction {
call(String a, String b, String c) => '$a $b $c!';
}
main() {
var cf = new ClassFunction();
var out = cf("dongnao","flutter","damon");
}
实现call方法可以让类像函数一样被调用
Mixin
abstract class Transportation {
void transport();
}
class Bicycle extends Transportation {
String safeIndex() => 'low';
String powerUnit() => '两个轮子';
String engery() => '脚蹬';
@override
void transport() {
print('${safeIndex()}+${powerUnit()}+${engery()}');
}
}
class Moto extends Transportation {
String safeIndex() => 'low';
String powerUnit() => '两个轮子';
String engery() => '汽油';
@override
void transport() {
print('${safeIndex()}+${powerUnit()}+${engery()}');
}
}
class Car extends Transportation {
String safeIndex() => 'middle';
String powerUnit() => '四个轮子';
String engery() => '汽油';
@override
void transport() {
print('${safeIndex()}+${powerUnit()}+${engery()}');
}
}
使用Mixin机制
abstract class Transportation {
void transport();
}
abstract class TwoWheel {
String powerUnit() => '两个轮子';
}
abstract class FourWheel {
String powerUnit() => '四个轮子';
}
abstract class LowSafe {
String safeIndex() => 'low';
}
abstract class MiddleSafe {
String safeIndex() => 'middle';
}
abstract class BodyEnergy {
String engery() => '脚蹬';
}
abstract class GasEnergy {
String engery() => '汽油';
}
class Bicycle extends Transportation with TwoWheel, LowSafe, BodyEnergy {
@override
void transport() {
print('${safeIndex()}+${powerUnit()}+${engery()}');
}
}
class Moto extends Transportation with TwoWheel, LowSafe, GasEnergy {
@override
void transport() {
print('${safeIndex()}+${powerUnit()}+${engery()}');
}
}
class Car extends Transportation with FourWheel, MiddleSafe, GasEnergy {
@override
void transport() {
print('${safeIndex()}+${powerUnit()}+${engery()}');
}
}
Minx机制中顺序
class A {
String getMessage() => 'A';
}
class B {
String getMessage() => 'B';
}
class P {
String getMessage() => 'P';
}
class AB extends P with A, B {}
class BA extends P with B, A {}
class ABO extends P with B implements A{
String getMessage() => '本身';
}
class ABI extends P with B implements A{}
void main() {
print(AB().getMessage()); //输出B
print(BA().getMessage()); //输出A
print(ABO().getMessage()); //输出本身
print(ABI().getMessage()); //输出B
}
小结
本方法>with最后一个>with其它>implement
泛型
Java中的泛型信息是编译时的,泛型信息在运行时是不存在的
Dart的泛型类型是固化的,在运行时也有可以判断的具体类型
库
使用核心库
import 'dart:Math'
void main(){
print(sqrt(8));
}
使用第三方库
pubspec.yaml
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.0
dio: ^2.1.0
XX.dart中
import "package:dio/dio.dart";
导入文件
import 'mylib.dart';
导入文件冲突
import 'MyLib1.dart' as lib1;
import 'MyLib2.dart' as lib2;
void main() {
var myLib = lib1.MyLib();
var myLib2 = lib2.MyLib();
}
选择性载入
import 'Mylib1.dart' as lib1 show Test;
import 'Mylib2.dart' as lib2 hide Test;
var test = lib1.Test();
var lib = lib2.MyLib();
延迟载入
import 'MyLib1.dart' deferred as lazyLib;
void main() {
lazyLoad();
}
lazyLoad() async {
await lazyLib.loadLibrary();
var t = lazyLib.Test();
t.test();
}
自定义库
mylib/tool.dart
part of mylib;
void printTool() => print('tool');
mylib/util.dart
part of mylib;
void printUtil() => print('util');
mylib/mylib.dart
library mylib;
part 'util.dart';
part 'tool.dart';
void printMyLib() => print('mylib');
main.dart
import 'mylib/mylib.dart';
void main() {
printMyLib();
printUtil();
printTool();
}
异步
####async和await
返回的Future对象
如果需要监听“完毕”这个状态,那么用whenComplete,需要监听“成功”这个状态,用then,需要监听“失败”这个状态,用catchError。
import 'dart:async';
void main() {
getName();
}
Future<void> getName() async {
await getStr(); //等getStr做完
print('name');
}
getStr() {
print('getStr');
}
打印输出 getStr
name
void main() {
getName();
getName2();
getName3();
}
Future<void> getName() async {
await getStr(); //等getStr做完
print('name');
}
getStr() {
print('getStr');
}
Future<void> getName2() {
print('name2');
}
Future<void> getName3() {
print('name3');
}
打印输出
getStr
name2
name3
name
void main() {
Future(() => futureTask())
.then((i) => 'abc$i') //abc10
.then((m) => print('$m')) //abc10
.then((w) => Future.error('出错了'))
.whenComplete(() => print('whenComplete'))
.catchError((e) => print(e), test: (Object o) {
print('test');
return false;//返回false就不会捕获,重新抛出去
});
}
futureTask() {
return 10;
}
打印输出
abc10
whenComplete
test
[ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: 出错了
null
如果改成return true
打印得到
abc10
whenComplete
test
出错了
Event-Looper
Dart中的Main Isolate只有一个Event Looper,但是存在两个Event Queue: Event Queue以及Microtask Queue。
void main(){
testFuture();
}
void testFuture() {
Future f = new Future(() => print('f1'));
Future f1 = new Future(() => null);
//Future f1 = new Future.delayed(Duration(seconds: 1) ,() => null);
Future f2 = new Future(() => null);
Future f3 = new Future(() => null);
f3.then((_) => print('f2'));
f2.then((_) {
print('f3');
new Future(() => print('f4'));
f1.then((_) {
print('f5');//微任务队列
});
});
f1.then((m) {
print('f6');
});
print('f7');
}
打印输出
f7
f1
f6
f3
f5
f2
f4
//微任务优先
import 'dart:async';
void main(){
testScheduleMicrotask();
}
void testScheduleMicrotask(){
scheduleMicrotask(() => print('s1'));
new Future.delayed(new Duration(seconds: 1), () => print('s2'));
new Future(() => print('s3')).then((_) {
print('s4');
scheduleMicrotask(() => print('s5'));
}).then((_) => print('s6'));
new Future(() => print('s7'));
scheduleMicrotask(() => print('s8'));
print('s9');
}
输出
s9
s1
s8
s3
s4
s6
s5
s7
s2
进阶
void testScheduleMicrotask() {
scheduleMicrotask(() => print('s1'));
new Future.delayed(new Duration(seconds: 1), () => print('s2'));
new Future(() => print('s3')).then((_) {
print('s4');
scheduleMicrotask(() => print('s5'));
}).then((_) => print('s6'));
new Future(() => print('s10'))
.then((_) => new Future(() => print('s11')))
.then((_) => print('s12'));
new Future(() => print('s7'));
scheduleMicrotask(() => print('s8'));
print('s9');
}
输出
I/flutter (31288): s9
I/flutter (31288): s1
I/flutter (31288): s8
I/flutter (31288): s3
I/flutter (31288): s4
I/flutter (31288): s6
I/flutter (31288): s5
I/flutter (31288): s10
I/flutter (31288): s7
I/flutter (31288): s11
I/flutter (31288): s12
I/flutter (31288): s2
生成器
同步生成器
使用sync*,返回的是Iterable对象。
yield会返回moveNext为true,并等待 moveNext 指令。
void main(){
var it = getSyncGenerator(5).iterator;
while (it.moveNext()) {
print(it.current);
}
}
Iterable<int> getSyncGenerator(int n) sync* {
print('start');
int k = 0;
while (k < n) {
yield k++;
}
print('end');
}
异步生成器
使用async*,返回的是Stream对象
调用getAsyncGenerator立即返回Stream, 执行了listen,函数才会开始执行。
listen返回一个StreamSubscription 对象进只有行流监听控制
import 'dart:async';
void main() {
//getAsyncGenerator(5);
//订阅
StreamSubscription subscription = getAsyncGenerator(5).listen(null);
subscription.onData((value) {
print(value);
if (value >= 2) {
subscription.pause();
}
});
}
Stream<int> getAsyncGenerator(int n) async* {
print('start');
int k = 0;
while (k < n) {
yield k++;
}
print('end');
}
隔离(Isolates)
所有Dart代码都在隔离区内运行,而不是线程。每个隔离区都有自己的内存堆,确保不会从任何其他隔离区访问隔离区的状态。
##注解
@deprecated
void main() {
dynamic tv = new Television();
tv.activate();
tv.turnOn();
}
class Television {
@deprecated
void activate() {
turnOn();
}
void turnOn() {
print('Television turn on!');
}
}
@override
void main() {
dynamic tv = new Television();
tv.activate();
tv.turnOn();
tv.turnOff();
}
class Television {
@deprecated
void activate() {
turnOn();
}
void turnOn() {
print('Television turn on!');
}
@override
noSuchMethod(Invocation mirror) {
print('没有找到方法');
}
}
自定义注解
test.dart中
class ToDo {
final String name;
final String what;
const ToDo({this.name, this.what});
}
main.dart中
import 'package:flutter_app/111.dart';
void main() {
......
}
class Television {
@ToDo(name:'csy', what:'create')
void doSomething() {
print("dosomething");
}
}