1.Flutter环境搭建
1.1. 下载AndroidStudio,下载flutter对应的sdk,可以使用gitee clone.gitee.com/mirrors/Flu… 选中对应的版本sdk.flutter bin目录下双击dart 或者flutter下载到依赖文件到cache。
1.2. 设置环境变量 open ~/.bash_profile
export PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
#添加flutter相关工具到path
export FLUTTER_ROOT=/Users/edy/Desktop/myuser/flutter
export PATH=${PATH}:$FLUTTER_ROOT/bin:$PATH
#添加dart相关工具到path
export DART_ROOT=/Users/edy/Desktop/myuser/flutter/bin/cache/dart-sdk
export PATH=${PATH}:$DART_ROOT/bin:$PATH
#Flutter镜像
#国内用户需要设置
export PUB_HOSTED_URL=https://pub.flutter-io.cn
#国内用户需要设置
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
#Android环境变量
export ANDROID_HOME=/Users/edy/Library/Android/sdk
#Android平台工具路径
export PATH=${PATH}:/Users/edy/Library/Android/sdk/platform-tools
#Android-tools路径
export PATH=${PATH}:/Users/edy/Library/Android/sdk/tools
#Android-模拟器路径
export PATH=${PATH}:/Users/edy/Library/Android/sdk/emulator
1.3. 执行 flutter doctor
2.Dart语言
2.1. var关键字
1. var关键字 变量。
var t = "hi world";
2.2. dynamic关键字 和Object关键字
1.`dynamic`与`Object`声明的变量都可以赋值任意对象
dynamic t;
Object x;
t = "hi world";
x = 'Hello Object';
//下面代码没有问题
t = 1000;
x = 1000;
2.`dynamic`与`Object`不同的是`dynamic`声明的对象编译器会提供所有可能的组合,而`Object`声明的对象只能使用 `Object` 的属性与方法, 否则编译器会报错
dynamic a;
Object b = "";
a = "";
print(a.length);
// print(b.length);//编译不通过。
// print(a.len); //运行时报错。
2.3. final 和 const
一个 `final` 变量只能被设置一次,两者区别在于:`const` 变量是一个编译时常量(编译时直接替换为常量值),`final`变量在第一次使用时被初始化。
被`final`或者`const`修饰的变量,变量类型可以省略
final str = "hi world";
//final String str = "hi world";
const str1 = "hi world";
final a = DateTime.now();
//final 运行时定义常量。
2.4.空安全
int i;
print(i*8);//会报错,因为i没有初始化。
if(i != null) {
print(i*8);//如果设置int? i;就不会走到这一步了。
}
Function? func;
func?.call();//fun不为空的时候则会调用。
2.5.函数
2.5.1.没有显式返回值,函数作为变量,函数作为参数。
如果没有显式声明返回值类型时,会默认当作dynamic处理。
isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
// 如果函数体只是一个表达式,可以使用=>来写。
bool isNoble (int atomicNumber)=> true ;
//函数可以作为变量
var say = (str){
print(str);
};
say("hi world");
//函数可以作为参数传递
//定义函数execute,它的参数类型为函数
void execute(var callback) {
callback(); //执行传入的函数
}
//调用execute,将箭头函数作为参数传递
execute(() => print("xxx"))
2.5.2.函数参数分为位置参数,(位置参数可以有可选位置参数),可选命名参数。
print(say("zhangsna", "wnagwu","and"));
print(enableFlags(bold: true));
2.6.类 构造函数,命名构造函数
Person.now() {
print("命名构造函数");
}
//默认的构造函数的简写
// Person(this.name, this.age);
Person(String name,int age) {
this._name = name;
this.age = age;
print("默认构造函数");
}
Person.setInfo(String name,int age) {
this._name = name;
this.age = age;
}
2.7.mixin,抽象类,接口
2.7.1.mixin
mixin Eat {
eat(){
print("eat");
}
}
mixin Walk {
walk(){
print("Walk");
}
}
mixin Code {
code(){
print("Code");
}
}
class Dog with Eat,Walk{
show(){
print('${this.eat()} ${this.walk()}');
}
}
class Man extends Person with Eat,Walk,Code{
show(){
print('${this.eat()} ${this.walk()} ${this.code()}');
}
}
2.7.2. 抽象类
class Person extends PersonAbstract {
show(){
this.eat();
this.run();
this.code();
this.rrr();//"base ... rrr"
}
}
abstract class PersonAbstract {
//抽象类里面有非抽象方法。
rrr(){
print("base ... rrr");
}
void eat(){
print("eat");
}
void run(){
print("run");
}
void code(){
print("code");
}
}
2.7.3. 接口 可以实现多个接口,implement
class SqlDatabase implements Database,Database1 {
abstract class Database {
String name;
void insert();
void delete();
void update();
void select();
}
//implements实现接口
class SqlDatabase implements Database {
SqlDatabase(this.name);
@override
void delete() {
// TODO: implement delete
}
@override
void insert() {
// TODO: implement insert
}
@override
void select() {
// TODO: implement select
}
@override
void update() {
// TODO: implement update
}
@override
String name;
}
2.8 异步支持 Future
Dart类库有非常多的返回`Future`或者`Stream`对象的函数。 这些函数被称为**异步函数**,表示一个异步操作的最终完成(或失败)及其结果值的表示。
(2.8.1)Future.then 和 await 返回值实现是一样的。
Future.delayed(Duration(seconds: 2),(){
return "hi world!";
}).then((data){
print(data);
});
await Future.delayed(Duration(seconds: 2));
return "hello";
(2.8.2)Future.catchError,onError 失败的时候会走到这两个方法里面。
Future.delayed(Duration(seconds: 2),(){
//return "hi world!";
throw AssertionError("Error");
}).then((data){
//执行成功会走到这里
print("success");
}).catchError((e){
//执行失败会走到这里
print(e);
});
(2.8.3)Future.whenComplete 不论是失败还是成功都会走到这里。
Future.delayed(Duration(seconds: 2),(){
//return "hi world!";
throw AssertionError("Error");
}).then((data){
//执行成功会走到这里
print(data);
}).catchError((e){
//执行失败会走到这里
print(e);
}).whenComplete((){
//无论成功或失败都会走到这里
});
(2.8.4)Future.wait 等待其他Future执行完成,然后then再执行其他。
Future.wait([
// 2秒后返回结果
Future.delayed(Duration(seconds: 2), () {
return "hello";
}),
// 4秒后返回结果
Future.delayed(Duration(seconds: 4), () {
return " world";
})
]).then((results){
print(results[0]+results[1]);
}).catchError((e){
print(e);
});
2.8.5 async/await
为了避免下面的回调地狱
login("alice","******").then((id){
//登录成功后通过,id获取用户信息
getUserInfo(id).then((userInfo){
//获取用户信息后保存
saveUserInfo(userInfo).then((){
//保存用户信息,接下来执行其他操作
...
});
});
})
2.8.5 消除1
ogin("alice","******").then((id){
return getUserInfo(id);
}).then((userInfo){
return saveUserInfo(userInfo);
}).then((e){
//执行接下来的操作
}).catchError((e){
//错误处理
print(e);
});
2.8.5 消除2
task() async {
try{
String id = await login("alice","******");
String userInfo = await getUserInfo(id);
await saveUserInfo(userInfo);
//执行接下来的操作
} catch(e){
//错误处理
print(e);
}
}
2.8.6 Stream
Stream.fromFutures([
// 1秒后返回结果
Future.delayed(Duration(seconds: 1), () {
return "hello 1";
}),
// 抛出一个异常
Future.delayed(Duration(seconds: 2),(){
throw AssertionError("Error");
}),
// 3秒后返回结果
Future.delayed(Duration(seconds: 3), () {
return "hello 3";
})
]).listen((data){
print(data);
}, onError: (e){
print(e.message);
},onDone: (){
print("onDone");
});
I/flutter (17666): hello 1
I/flutter (17666): Error
I/flutter (17666): hello 3
onDone