变量
-
var
关键词
使用var
声明的变量,默认是dynamic
【类似于泛型】
var varA;
//赋值为整型
varA = 10;
//注意,改变变量类型是不可接受的,可以理解为swift中的类型推断,也就是所说的类型安全。
varA = "ten";
Error: A value of type 'int' can't be assigned to a variable of type 'String'.
我也很好奇的尝试了一下 let
let year = "2019";
Error: A value of type 'String' can't be assigned to a variable of type 'invalid-type'.
//显然,Dart 并没有这个关键词用于限定不可变类型,不过有其它的。
Dart是面向对象的语言,其中所有对象和类型都继承于Object
基类
注意 Object
的O
是大写的!!!
-
dynamic
关键词
dynamic valueT = "string value";
//可以放心的指向任意类型了
valueT = 100;
-
Object
声明的对象 、同样能声明一个泛型
Object objA = "string value";
objA = 100;
区别
dynamic
声明的变量可以调用可能的方法,但是别想多了这个只能让你安全度过编译期,在运行期还是会检查函数签名的。
类似于
dynamic varA = "time";
varA.length;
varA.someFunction;
Error: get$someFunction is not a function.
varA.someFunction();
Error: someFunction$0 is not a function
//someFunction Dart的排异反应还是有的
Object
声明的变量,只能调用基类才有的方法
Object objA = "string value";
objA.length; //这里的效果可能就是,屏蔽了类型推断机制。
- 静态变量
const
关键词 【注意 可以不声明类型】
//编译时常量
const String valueA = "hi";
const valueB = "const";
final
关键词 【可不用声明类型】
//仅能被初始化一次,使用时初始化。
final String valueA = "hi";
final valueB = "final";
思考 如果进行类型转换 【类型转换实验】
var varA = 100;
//基于以往习惯 【错误】
String varB = String(varA);
//as 【错误】
String varC = varA as String;
//老老实实的 使用对象方法吧
String varD = varA.toString();
函数
Dart 中函数既可以作为参数,也可以作为一个类型,函数式编程的身影~~~
- 无返回值函数
void noReturnFunction(){
print("无返回值的函数");
}
void noReturnWithParamFunction(int value) {
print(value);
print("无返回值,但有参数的函数");
}
- 有返回值的函数
bool isEqual(int a, int b){
return a==b;
}
//未显示声明返回值类型,返回值 是被标记为 dynamic的。
isEqual_A(int a, int b){
return a==b;
}
插播一条,关于【函数简写】 如果函数体仅有一条语句
bool isEqual(int a, int b){
return a==b;
}
==》省略 {}
bool isEqual(int a, int b) => return a==b;
==》省略 返回值类型
isEqual(int a, int b) => return a== b;
==》省略 return
isEqual(int a, int b) => a==b;
==》别想了,这是不可能的...
isEqual => a==b;
插播第二条,关于【函数重载】
int isEqual(String strA, String strB) {
return strA.compareTo(strB);
}
bool isEqual(int a, int b){
return a==b;
}
Error: 编译器会告诉你,这个真的实现不了~~~
- 函数作为变量
var varF = (strValue) {
print("get $strValue ");
}
varF("Time");
- 使用
typedef
声明函数类型
typedef void noReturnFunction(String);
typedef String returnStringFunction(String);
...
- 函数作为参数传递 【想想var 和 dynamic 的联系和区别】
var varF = () {
print("hello");
}
void printFunction(var func){
func();
}
//调用
printFunction(varF);
- 函数【可选参数】
//想起了 OC 的 ...
void mutableParamsFunction(String a, ...){
读取参数列表 balabala...
...
}
Error: 别想了,也没戏
//这里 [] 用于表示可选参数
void optionFunction(String a, String b, [String c]) {
...
//使用可选参数时,需要判断
if(c != null) {
...balabala
}
}
//调用
optionFunction("hi","flutter");
optionFunction("hi","flutter","option");
- 函数【可选参数命名】
void optionParamsNameFunction({String strA, String strB}) {
...balabala
}
//实际效果 在调用的时候就能看出来了
optionParamsNameFunction(strA: "hi", strB: "flutter");
【注意】 一个有趣的尝试
optionParamsNameFunction(strB:"flutter", strA:"hi");
异步编程
Future 【感受 类似GCD 和 链式编程思想的结合体】
- 延时
//延时5秒
Future.delayed(new Duration(seconds:5),() {
...
}).then((anyThing){
...
});
Future中几乎所有可用的方法,均会返回Future本身,为实现链式调用创造了基础。
- 异常抛出及其捕获
> 1
Future.delayed(new Duration(seconds:2),(){
...
throw AssertionError("Error desc...");
}).then((anyThing){
//注意 一旦发生异常,此处代码不会被执行
}).catchError((e){
//捕获异常
print(e.message);
});
> 2 then 可选参数捕获异常
Future.delayed(new Duration(seconds:2),(){
throw AssertionError("Error desc...");
}).then((anyThing){
...
},onError:(e){
//可选参数 中捕获到异常
print(e.message);
});
> 3 无论是或否发生异常,最终均会执行的需求实现
Future.delayed(new Duration(seconds:2),(){
throw AssertionError("Error desc...");
}).then((anyThing){
...
}).catchError((e){
print(e.message);
}).whenComplete((){
...
print("do anything u want...");
});
- 异步事件同步 【相当于 GCD栅栏】
Future.wait([
//事件一
Future.delayed(new Duration(seconds:2),(){
return "wait";
}),
//事件二
Future.delayed(new Duration(seconds:4),(){
return " me please";
})
]).then((results){
//results 相当于整合了异步事件的所有结果到一个数组中
print(results[0] + results[1]);
}).catchError((e){
print(e);
});
- Future 函数改造
个人理解:可以将任意函数 返回值处理成Future对象
这一点尤其像RAC中的信号概念
//一个模拟获取用户名的函数
> 1 照葫芦画瓢
Future<String> getUserName() {
return "tom"
}
结果是编译器报错,大概意思就是 返回值 int 与 Future<String>类型冲突,
之后也尝试查找了有没有方法可以把任意类型包装成Future对象,但没有找到。
> 2 领悟到一点儿
Future<String> getUserName() async {
return "Saylor";
}
对一个函数 使用 async 关键词表明其运行在异步模式中时,
Dart编译器会自动将返回值进行Future对象封装。
【运行尝试】
getUserName().then((strName){
print(strName);
}).whenComplete((){
print("complete...");
});
- 回调地狱 Callback hell 【实际指的就是 block嵌套使用的情况】
现有的编程经历中,的确很多时候热衷于使用闭包,
但是积累到一定程度的时候往往会发现闭包使用过程中不可避免会出现嵌套。
[obj loginUserName:strName pwd:strPwd Result:^(str strUserId){
...
[obj getUserInfoWithUserId:strUserId Result:^(UserInfo * userInfo){
...
}];
}];
使用future 改善的原理其实就是,返回值是被封装的Future对象,进而能够形成链式调用。(个人缪解)
Future<String> login(String strName, String pwd) async {
... 网络请求 balabala...
strUserId = ...
return strUserId;
}
Future getUserInfo(String strUserId) async {
... 网络请求 balabala...
userInfo = ...
return userInfo;
}
//调用
login("saylor","pwd").then((strUserId){
return getUserInfo(strUserId);
}).then((userInfo){
//...
});
- await 异步变同步
【注意】 该关键词会阻塞当前线程,故必须运行在异步线程中!!!
//声明一个异步方法
task() async {
try{
String strUserId = await login("tom","***");
UserInfo userInfo = await getUserInfo(strUserId);
...
}catch(error){
print(error.message);
}
}
这种最显著的效果:以同步工作流的方式,去完成异步任务。
更符合猿类平时的编程习惯~~~
Stream 【流... 可以理解为 任务队列】
同Future 一样,主要应用于异步编程中。不同之处,在于Stream 可以将多个Future 任务组装成工作流,并监听各个任务的完成情况。
String.fromFutures([
Future.delayed(new Duration(seconds:1),(){
//task 1
...
return "res_1";
}),
Future.delayed(new Duration(seconds:1),(){
//task 2
...
return "res_2";
}),
... 可以自行累加
]).listen((res){
//这里 res , 不同于 Future.wait 中所做的处理,每一个任务完成均能够监听到。(多次执行)
...
}.onError:(error){
//捕获异常
print(error.message);
},onDone:(){
//工作流任务完成【全部完成】
});