Flutter
Dart 环境搭建
使用 vscode 开发 flutter 项目需要装Flutter和Dart插件(另外再加一个 code runner 插件,方便运行);
下载 Dart SDK,配置环境变量;
官网下载地址:https://dart.dev/get-dart/archive
;
去终端查看一下版本验证是否配置环境变量成功:dart --version
;
运行案例
dart 有个入口函数,main函数
并且一行代码结尾要用分号结束
main() {
print("hello");
}
输出要是有乱码重启 vscode 即可
声明变量
- 明确声明
- 类型推导
- 动态类型
明确类型
dart 是一门强类型的语言
void main(List<String> args) {
String foo = 'test';
int num = 1;
}
类型推导
- var
- const
- final
- dynamic
var、const、final
const 和 final 声明的变量不可以重新赋值
void main(List<String> args) {
var foo = 'test';
const foo1 = 'test';
final foo2 = 'test';
}
const 和 final 区别
const 必须直接赋值常量,final 可以通过运行时赋值
void main(List<String> args) {
const foo1 = test();// 报错
final foo2 = test();// 可以
}
int test() {
return 10;
}
dynamic
明确类型和类型推导中var、const、final声明的类型都是不可以改变的,而dynamic就可以;
开发中尽量少用 dynamic 类型,存在类型潜在危险
void main(List<String> args) {
dynamic foo = 'test';
foo = 123;
}
类型
- 数字类型 int、double
- 布尔类型 bool
- 字符串 String
- 集合类型 List、Set、Map
bool 类型注意
dart 中没有 非 0 即真 的说法
void main(List<String> args) {
var foo = 'test';
// 错误的写法
if(foo) {
print(foo);
}
// 这样写
if(foo != null) {
print(foo);
}
}
字符串 String
- 单双引号
- 三引号,可以换行
void main(List<String> args) {
var foo = 'test';
var foo1 = "test";
var foo2 = '''
abc
cba
'''
}
拼接
一般是**$**这样,当$直接跟一个变量时是可以省略的;
要是跟表达式就不可以省略;
void main(List<String> args) {
final name = 'zsf';
final age = 18;
print("name:$name age:$age");
print("${name.runtimeType}");
}
集合类型
- List,类似数组
- Set,元素唯一且无序
- Map,键值对
void main(List<String> args) {
List<String> names = ['zsf', 'kebe', 'zsf'];
// Set一般应用于Lsit的去重
Set<int> nums = {101, 111};
List<String> name1 = List.from(Set.from(names));
print(name1); // [zsf, kobe]
Map<String, dynamic> info = {
'name': 'zsf',
'age': 18,
};
}
dynamic 和 object 区别
dart 中所有的类都默认继承Object;
使用 dynamic 类型可以进行类型转化,而使用 Object 类型则不行;
函数
dart 中函数的定义是这样的
int sum(int num1, int num2) {
return num1 + num2;
}
参数
dart 中函数的参数有两种:必传参数和可选参数
必传参数
void main(List<String> args) {
sum(1, 2);
}
int sum(int num1, int num2) {
return num1 + num2;
}
可选参数
- 位置可选参数
- 命名可选参数
隐式可选参数
void main(List<String> args) {
printInfo(1);
printInfo(1, 2);
}
void printInfo(int num1, [int? num2, String? str]) {
print('$num1 $num2 $str');
}
命名可选参数
传可选参数时需要指名参数名字
void main(List<String> args) {
printInfo(1);
printInfo(1, num2: 2);
}
void printInfo(int num1, {int? num2, String? str}) {
print('$num1 $num2 $str');
}
默认值
默认值只能给可选参数,不可以给必传参数
void main(List<String> args) {
printInfo(1);
printInfo(1, num2: 2);
}
void printInfo(int num1, {int? num2, String? str = 'hhh'}) {
print('$num1 $num2 $str');
}
匿名函数
只有一行才能使用箭头函数
void main(List<String> args) {
List<String> names = ['zsf', 'hhh', 'kkk'];
names.forEach((item) {
print(item);
});
names.forEach((item) => print(item));
}
返回值
如果没有返回值,默认返回 null
运算符
大部分运算符与其它语言类似,下面只说不同的
整除
const num = 7;
print(num ~/ 3); // 2
??=赋值
- 如果有值,使用原来的值;
- 如果值为 null,则赋值;
var name = 'zsf';
name ??= 'hhh';
print(name); // zsf
??
var msg = null;
var res = msg ?? 'hello';
print(res); // hello
如果msg有值则赋值给res,没有则使用后面的'hello';
..级联
类和对象
dart 是面向对象的开发语言;
类一般有两部分:成员变量和方法;
dart2.5 之后,new 关键字可以省略;
void main(List<String> args) {
final p = new Person();
p.name = 'zsf';
p.eat();
}
class Person {
String? name;
void eat() {
print('${name}吃东西');
}
}
当 eat 函数内有同名变量(比如 name)时,需要使用 this,指明当前对象的 name,而不是根据词法作用域的 name;
构造函数
当类中没有构造函数,会默认创建一个无参的构造函数;
dart 没有函数的重载,也就是没有同名的方法;
void main(List<String> args) {
final p = new Person('zsf');
p.eat();
}
class Person {
String? name;
Person(String name) {
this.name = name;
}
void eat() {
print('${name}吃东西');
}
}
语法糖
void main(List<String> args) {
final p = new Person('zsf');
p.eat();
}
class Person {
String? name;
int? age;
Person({this.name, this.age})
void eat() {
print('${name}吃东西');
}
}
命名构造函数
当需要多种构造函数时,可以使用命名构造函数
初始化列表
void main(List<String> args) {
final p = new Person('zsf');
p.eat();
}
class Person {
String? name;
Person(String name) : name = 'zsf';
void eat() {
print('${name}吃东西');
}
}
常量构造函数
- const 修饰构造函数
- final 修饰成员变量
- const 声明实例
void main(List<String> args) {
const p1 = Person('zsf');
const p2 = Person('zsf');
print(identical(p1, p2)); // true
}
class Person {
final String? name;
const Person(this.name);
}
工厂构造函数
有一个特点:需要在函数内部明确返回一个对象
setter 和 geter
当需要监听属性的访问时,需要用到
继承
继承可以复用代码;
子类使用 super 访问父类;
当不满意父类方法可以重写,并且可以拥有自己的成员变量;
class Animal {
int age;
Animal(this.age);
run() {
print('在奔跑ing');
}
}
class Person extends Animal {
String name;
Person(String name, int age) : name=name, super(age);
@override
run() {
print('$name在奔跑ing');
}
@override
String toString() {
return 'name=$name, age=$age';
}
}
抽象类
- 使用关键字abstract修饰;
- 不能被实例化;
- 抽象类中可以定义抽象方法;
- 它的子类必须重写它的方法;
普通类是不能定义抽象方法的
什么是抽象方法?
只有定义,没有实现
void eat();
你可能会有个疑惑:抽象类有什么用?
实现多态
abstract class Shape {
getArea();
}
class Circle extends Shape {
double r;
Circle(this.r);
@override
getArea() {
return r * r * 3.14;
}
}
class Reactangle extends Shape {
double w;
double h;
Reactangle(this.w, this.h);
@override
getArea() {
return w * h;
}
}
接口
dart 中,默认所有类都是接口;
可以定义成抽象类,由其它类实现;
因为 dart 不能多继承,只能继承一个,当你想复用多个类的不同代码时,可以使用实现implements,也就是接口;
abstract class Runner {
run();
}
abstract class Flyer {
fly();
}
class SuperMan implements Runner, Flyer {
@override
run() {
print('超人在奔跑');
}
@override
fly() {
print('超人在飞');
}
}
mixin 混入
也是代码复用的一种方案
- 关键字 mixin 定义类
- with 关键字混入
main(List<String> args) {
var superMan = SuperMain();
superMan.run();
superMan.fly();
}
mixin Runner {
run() {
print('在奔跑');
}
}
mixin Flyer {
fly() {
print('在飞翔');
}
}
// implements的方式要求必须对其中的方法进行重新实现
// class SuperMan implements Runner, Flyer {}
class SuperMain with Runner, Flyer {
}
泛型
可以让使用者决定类型,能写出更多通用性的代码
main(List<String> args) {
Location l2 = Location<int>(10, 20);
print(l2.x.runtimeType); // int
Location l3 = Location<String>('aaa', 'bbb');
print(l3.x.runtimeType); // String
}
class Location<T> {
T x;
T y;
Location(this.x, this.y);
}
库
dart 任何一个文件都是一个库,即使没有使用关键字library声明;
- 标准库
- 自定义
- 第三方
标准库
dart:io、dart:math、dart:html、dart:core 等等
import 'dart:io'
自定义
import 'lib/student/student.dart';
第三方
//Pub包管理系统中有很多功能强大、实用的库,可以使用前缀 package:
import 'package:flutter/material.dart';
选择性导入
如果希望只导入
库中某些内容,或者刻意隐藏
库里面某些内容,可以使用show
和hide
关键字
import 'lib/student/student.dart' show Student, Person;
import 'lib/student/student.dart' hide Person;
起别名
当各个库有命名冲突的时候,可以使用as关键字
来使用命名空间
import 'lib/student/student.dart' as Stu;
Stu.Student s = new Stu.Student();
项目
创建 flutter 项目
- 命令行
- 工具(比如 Android studio)
命令行
flutter create learn_flutter
注意项目名不能由特殊符号、驼峰
默认项目分析:
- 在目录下有一个
lib
文件夹,里面会存放 我们编写的 Flutter 代码; - 打开发现里面有一个
main.dart
,它是我们 Flutter 启动的入口文件
,里面有main函数
;
运行
终端执行flutter run