Flutter简介
- Flutter是Google推出并开源的移动应用开发框架,主打跨平台、高保真、高性能。开发者可以通过Dart语言开发App,一套代码同时运行在ios和安卓平台。提供组件、接口,开发者可以很快的为Flutter添加native扩展。同时Flutter还使用Native引擎渲染视图,为用户提供良好的体验
- 特点
跨平台自绘引擎
高性能:页面刷新、通信等
Flutter开发环境配置
- 获取Flutter SDK并解压缩
官网地址
http://flutter.io/sdk-archive/#windows
也可以从官方的github上下载:
https://github.com/flutter/flutter/releases
- 设置环境变量
在path中添加flutter/bin的全路径
- 运行flutter doctor命令,检察环境是否有未安装的依赖
首先要打开电脑中安装的Android Studio,如果没有的话,一定要安装的
- 升级flutter的命令:flutter upgrade
- 打开Android Studio,file,New Flutter Project,选择Application(应为实际开发的是程序)
dart_开发环境配置
1.下载
下载链接https://gekorm.com/dart-windows/
选择第一个稳定版本
打开安装包,按步骤下载
2.如何与开发工具结合
可以打开intelliJ IDEA
,然后在file里面点击new project
不过在这之前,需要装flutter
和dart
选择dart工程,输入dart sdk路径
创建完成之后会生成一个dartstudy.dart
文件,可以运行它,会打印出Hello,World
这个命令行工程,在这个main里面可以运行希望写的东西
void main () {
print('Hello, World')
var str = "hello world" //创建了一个变量
print(str);
}
//点击运行按钮会跳出
//Hello, World 这是打印字符串
//hello world 这个是打印的变量
dart_ 变量与常量
dart变量声明
首先,dart是一个强类型的编程语言.
与js不同,js可以不声明类型.而且js在编译阶段是不会去检查类型的.
dart需要在声明的时候首先去声明它的类型,但是他也具备和js一样的var
声明方式
void main() {
//var 声明
var username = "quan";//这个时候并没有声明username的类型,应为用的是var
//和js不一样的点在于,声明之后这个username的类型,就已经通过值来判断出来了
//比如这里,是把一个字符串"quan"赋给了username,这个时候dart的编译系统就会推断出来一个字符串类型
//所以接下来给username赋值的时候,只能给字符串类型,不能给数字类型👇
username = 123; //会报错的,123下面会有红色曲线
username = "good";//这个才是对的
//注意:对dart来讲,所有的 对象 都是继承于odject类型的
//js中最顶端是 undefined
//dart中的最顶端是 object 👇
Object password = 123;//先object类型
password = "goodjob";//这边把字符串赋给password不会报错,应为object是最顶端,
//字符串类型是它的子类型,所以不会报错
//dynamic类型(动态类型)
//dynamic类型他也是更像object类型,也是一个非常大的类型,但是他跟objec不一样的点在于👇
//比如上面有object这个变量,然后下一行写"password.",这个"."后面的时候,只会有object拥有的属性和方法(图 1)
//但如果定义dynmic类型
dynamic psw2 = 123;
psw2.toString();//这里面.后面可以是任何方法都不会报错(图2)
//所以,dynamic相当于推断所有可能的属性和方法,而并不是只有object具有的属性和方法(容易导致引入运行时错误)
}
图1
图2
例子
void main() {
var username = "123"
username = "good"
dynamic a = "good job";
Object b = "good job";
//分别打印一下他们的长度
print(a.length);//不报错
print(b.length);//报错
//所以更推荐object方法,应为object在编译是就会告诉你报错,而dynamic在运行是才告诉你,容易出bug
}
常量声明
常量就是只能声明一次值,之后就不能再变了,在dart里面常量有两种声明方式
①final
final psw = "good";
pws = "job"; // 会报错(编译错误,不可以重新赋值)
②const
const psw = "good"
psw = "job" //也会报错
两者区别(先占内存还是后占内存)
- const是编译时常量:就是在编译阶段,它就已经会存在了(代码在启动的时候就已经存在了,虽然没有运行到它,但是它已经准备好了)[速度快]
- final是在第一次使用是才被初始化,就是你什么时候用到它 ,它什么时候去申请一块内存空间,才会去真正导到内存里去
dart_数据类型
void main() {
// 1. num类型:有两个子类型 int(整型) 和 double(双精度浮点型)
int abc = 110;//整数
//我们也是可以把一个字符串转换成int类型的👇
int a = int.parse("119")
double cde = 200.111//可以写小数点,int类型就不可以写
double b = double.parse("111.222")
//也可以把数值转换成字符串👇
// 2. String类型
String good = 123.toString()//这边是把int类型转换成了字符串类型,赋值给good
//可以四舍五入
String.job = 123.3333.toStringAsFixed(2);//AsFixed()是保留几位小数
// 3. 布尔bool类型,true or false
bool result = 123 > 110;
print(resule)
//运行结果为true
bool result = 1 == '1'
print(result)
//运行结果为false(类型就不相同,就不会去进行值的比较了)
// 4. List类型(数组类型)
List list = [1,3,5,7,9]
//声明一个空数组
List alist = new List()//可以往里面放一些值进去
alist.add(2);
alist.addAll([2,4,6,8,10])
print(alist)
//运行结果为 [2,4,6,8,10]
//也可以打印它的长度
print(alist.length)//长度为5
//取第一个或最后一个元素
print(alist.first);
print(alist.last);
//通过下标
print(alist[2]);
// 5. Map类型(对象类型) 本质就是keyvalue的键值对,也有两种声明方式
//①直接用大括号
Map obj = ['x':1, 'y':2, 'z':3]; //要用单引号或双引号包裹
//② new一个
Map obj2 = new Map();
obj2['x'] = 1;
obj2['y'] = 2;
print(obj);
print(obj2);
//运行结果:
//① [x:1, y:2, z:3]
//② [x:1. y:2]
print(obj.containsKey('x')) //containsKey判断是否包含某个key值
//true
print(obj.containsKey('a'))
//false
obj.remove('y')//删除,''里面放属性,这边是删掉y
print(object)
//[x:1, z:3]
}
dart_function
对于每个应用程序都要具备一个入口函数,这里的入口函数就是main
void main() {
//main前面是一个返回值的类型,如果不需要任何返回值的话的就写void
}
- 写一个自己的函数,方法名getusername,要求返回值是String类型
void main() {
String username = getUserName();
String userInfo = getPersonInfo(111);
print(userInfo);
int age = addAge(111,2);
print(age);
//113
int age = addAge(111);
print(age);
//111
int age2 = addAge2(age1:119, age2:1)
print(age2)
//120
int age2 = addAge2(age1:119)
print(age2)
//119
//匿名函数:一个不具备方法名的函数,他在某个方法里面的回调经常会用到
var list = ["acb", "cde", "def"]
//它可以循环
list.forEach((str) [ //小括号里面是它的值,我们写个str
print(str);
])
//abc
//cde
//def
}
String getUserName() { //这边如果把String改成void就会出现编译错误,应为这边给他void没有返回值,但是main中却把它拿过来赋值了
return 'hello world';
}
//这边再写一个接收参数的
String getPersonInfo(int userId) {
Map userInfoObj = [
"111":"zhangsan";
"222":"lisi";
]
return userInfoObj[userId.toString()];//userId当作key属性,放到这里
//应为userId是int类型,但是userInfoObj里面"111"是字符串类型,所以要toString一下,不然main中print userInfo就是"null"
}
//可选参数:应为不是每一个参数都要传进去
int addAge(int age1, [int age2]) {//int age2的写法的意思是,不想要age2必填,[]表示他是可选参数
return age1 + (age2 !=null ? age2 : 0);
}
//但是用"[]"的话,得写(age2 !=null ? age2 : 0)这个,很麻烦,所以可以给他默认值
int addAge2({int age1, int age2=0}) { //但是用默认值的时候,需要在所有参数外面包上{}
return age1 + age2;
}
dart_类与继承
dart是一种完全面向对象的编程语言,所以里面有非常标准的类的概念
void main() {
var p = new Person();
p.age = 123;
print(p);
//Instance of 'person' ,打印出来,告诉我们这是一个实例
print(p.age)
//123
}
class Person {
int age;//定义了一个属性
String name;
}
//但是我们期望它在实例化阶段阶变成一个值了,所以我们这个时候需要一个构造函数
//constraint
void main() {
var p = new Person(23,"zhangsan");
print(p.age);
//23
print(p.name);
//zhangsan
//这里可以直接调用p.sayHello
p.sayHello();
//就会直接打印:my name is:zhangsan
var y = new Worker(18,'list',3500);
w.sayHelo();//my salary is:3500
}
class Person {
int age;//定义了一个属性
String name;
//构造函数
Person(int age, String name) {
this.age = age;//指向Person实例化后的这个实例
this.name = name;
}
//当然也可以让这个类具备一些能力,他现在只能接受参数,就是他自己的成员方法
void sayHello() {
//这样他就可以做一些事情
print('my name is' + this.name);
}
}
//如果想要继承例外一个类的话,我们只要使用extends这个关键字
//比如在这边要做一个子类
class Worker extends Person {
//Worker(int age,String name) : super(age, name)//构造器
//这相当于我们做了一个关于Worker的构造函数,它调的这个super是一个父类构造器
//我们还可以对这个构造器进行扩展 →
//Worker(int age,String name, int salary) : super(age, name)
//还需要添加一个成员变量 int salary
//下面是完整的👇
int salary;
Worker(int age,String name, int salary) : super(age, name) {
this.salary = salary;
}
//告诉编译器和程序员,这是一个重写,就是覆盖父类里面同名方法
void sayHello() {
//如果在这个子函数里面,我还想调父函数的这个sayHelo,然后再调一下我的工资
super.sayHello();//如果要调用父类里面的方法的话,就要加上 super 代表它的父类
print('my salary is:' + this.salary.toString())
}
}
dart_mixin与抽象类
混合
- dart里面只有单继承,就是不能同时继承多个父类
- 如果想要有多个父类继承的这样的需求的话,只能通过混合的方式去实现
void main() {
var p = new Person(19,'zhangsan');
p.eat();
p.sleep();
p.sayHello();
}
class Eat {
void eat() {
print('eat');
}
void sayHello() {
print('say Hello in eat');
}
}
class Sleep {
void sleep() {
print('sleep');
}
void sayHello() {
print('say Hello in eat');
}
}
class Person with Eat,Sleep {
int age;
String name;
Person(int age, String name) {
this.age = age;
this.name = name;
}
void sayHello() {
print('my name is' + this.name);
}
}
//如果类里面有方法,混合里面也有的话,优先使用类自身具备的方法,如果只有混合里面有同名的方法的话,那么在最后面的会生效.
//同名方法,后面的会把前面的覆盖调
抽象类
Dart中抽象类: Dart抽象类主要用于定义标准,子类可以继承抽象类,也可以实现抽象类接口。
- 抽象类通过 abstract 关键字来定义
- Dart中的抽象方法不能用abstract声明,Dart中没有方法体的方法我们称为抽象方法。
- 如果子类继承抽象类必须得实现里面的抽象方法
- 如果把抽象类当做接口实现的话必须得实现抽象类里面定义的所有属性和方法。
- 抽象类不能被实例化,只有继承它的子类可以
extends抽象类 和 implements 的区别:
- 如果要复用抽象类里面的方法,并且要用抽象方法约束自类的话我们就用extends继承抽象类
- 如果只是把抽象类当做标准的话我们就用implements实现抽象类
// 定义一个Animal 类要求它的子类必须包含eat方法
abstract class Animal {
eat(); // 抽象方法
run(); // 抽象方法
printInfo() {
print('我是抽象类里的普通抽象方法');
}
}
class Dog extends Animal {
eat() {
// TODO: implement eat
print('小狗在吃骨头');
}
run() {
// TODO: implement run
print('小狗在跑');
}
}
class Cat extends Animal {
eat() {
// TODO: implement eat
print('小猫在吃老鼠');
}
run() {
// TODO: implement run
print('小猫在跑');
}
}
main() {
Dog d = new Dog();
d.eat(); // 小狗在吃东西
d.run(); // 小狗在跑
d.printInfo(); // 我是抽象类里的普通抽象方法
Cat c = new Cat();
c.eat(); // 小猫在吃东西
c.run(); // 小猫在跑
c.printInfo(); // 我是抽象类里的普通抽象方法
// Animal a = new Animal(); // 抽象类没法直接被实例化
}
dart_异步处理
Future
Future表示一个异步任务的最终完成或失败及其结果值得表示,一个Future只会对应一个结果:成功或失败,Future的返回值仍然是一个Future对象。
Future在执行过程可以划分为两种状态:
- 未完成状态:执行Future内部的任务
- 完成状态:当Future内部的任务执行完成,通常会返回一个值或抛出一个异常
void main(List<String> args) {
print("start");
Future(() {
sleep(Duration(seconds: 2));
print("执行任务");
return "hello";
// throw Exception("发生异常了");
}).then((value) {
print("value: $value");
}).catchError((error) {
print("error: $error");
}).whenComplete(() {
print("执行完毕!!!");
});
print("end");
}
//start
//end
//执行任务
//value: hello
//执行完毕!!!
Future.value()
直接获取一个完成的Future,会直接调用then函数。
void main(List<String> args) {
print("start");
Future.value("hello").then((value) {
print(value);
});
print("end");
}
//start
//end
//hello
main(List<String> args) {
Future(() {
return "hello";
}).then((value) {
return value + " world";
}).then((value) {
print(value);
});
}
//hello world
Future.error()
void main(List<String> args) {
print("start");
Future.error(Exception("这是一个异常")).catchError((error) {
print(error);
});
print("end");
}
//start
//end
//Exception: 这是一个异常
Future.delayed()
延迟执行任务。
void main(List<String> args) {
print("start");
Future.delayed(Duration(seconds: 2), () {
return "hello world";
}).then((value) {
print(value);
});
print("end");
}
//start
//end
//hello world
Future.wait()
等待多个异步任务执行完后进行操作。
void main(List<String> args) {
print("start");
Future.wait([
Future.delayed(Duration(seconds: 2), () {
return "hello";
}),
Future.delayed(Duration(seconds: 3), () {
return "world";
})
]).then((value) {
print("成功:$value");
}).catchError((error) {
print("失败:$error");
});
print("end");
}
//start
//end
//成功:[hello, world]
async和await
async
:用于声明函数,表示这个函数是异步函数,其返回值类型是Futureawait
:将异步结果Future<T>
转换为T
void main(List<String> args) {
print("start");
getTask().then((value) {
print(value);
});
print("end");
}
Future<String> getTask() async {
print(1);
var result = await Future.delayed(Duration(seconds: 2), () {
return "hello";
});
print(2);
return result + " world";
}