拉钩
基础

基础环境:
操作系统 git vscode 网络
window 下只能搭建安卓开发环境
mac 下既可以搭建安卓开发环境也可以搭建 ios 开发环境
磁盘空间:
window400+ mac 700m+
git: flutter 开发需要 git 支持
下载 https//git-scm.com/download
安装: 双击下一步
git --version 能看到 git 环境安装成功
vscode 安装 fluuter 插件
中文官网
https://docs.flutter.cn/community/china/
window 环境搭建
jdk
android studio(android studio android sdk android 模拟器)
flutter sdk
配置资源镜像:
由于国内访问 flutter 有时可能会收到限制,flutter 官方为空过开发者搭建了临时镜像,大家可以将下面的资源地址加入到环境变量中:
PUB_HOSTEDURL=https//pub.flutter-io.cn
FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn

JDK
下载地址:https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html
安装 android stuio


flutter doctor 检测环境是否满足
版本切换解决问题

查看模拟器
flutter emulators
启动模拟器
flutter emulators --launch Pixel_3a_XL_API_33
https://blog.csdn.net/qq_40166103/article/details/125673747
dart 与 javascript 差异
| Dart | JavaScript |
|---|---|
| Flutter | React |
| https://pub.dev | https://npmjs.com |
| pub | npm |
dart 官网介绍:https://dart.cn/get-dart
环境变量
1.flutter\bin
包含 flutter 和 Dart 的相关执行命令
2.flutter\bin\cache\dart-sdk\bin
包含 Dart SDK 的相关命令的执行路径
3.flutter\.pub-cache\bin
pub 下载的公共模块的执行路径
资源网站
英文官网:https://dart.dev
中文官网:https://dart.cn
在线运行地址:
https://dartpad.dartlang.org/
https://dartpad.cn/
生态:
https://pub.dev/
dart 基础语法:
注释语法和js一致
声明函数不需要关键字(js中通过function关键字来声明函数)
函数和参数前面都有类型声明,void表示没有返回值,int是整型数字
打印使用print(js使用console.log())
每行代码结束时,必须写结束分号(;)
字符串通过引号包起来,支持模板字符串
main是入口函数,Dart应用程序总是从main函数开始执行
用var声明的变量,其数据类型是动态的
dart 基础语法注释
单行注释 //
都行注释 /*注释内容*/
文档注释 ///
可以通过dartdoc将注释转换成文档(文档注释支持markdown语法)
基础语法-变量
变量是一个引用,dart万物皆对象,变量存储的是对象的引用
声明变量
1.明确指定类型:int age = 18;
2.不明确类型:var age=18;或 dynamic age = 18;
变量名大小写敏感(age 与 Age是两个不同的变量)
变量默认值是null(js中变量默认值是undefined)
Dart变量的值是不会进行隐式转换(null不会自动转换成false)
基础语法-常量
常量是值不可该表的变量(一旦声明 其值不能更改)
声明常量
const age = 18;(编译时)
final age = 18;(运行时+编译时)
const 与 final 的区别
const time = DateTime.now();//报错 无法将运行时的值分配给const
final time = DateTime.now();//成功-可以将运行时的值分配给final变量
基础语法-数据类型
Number String Boolean List Set Map 其他
num 数字类型(既可以是证书,也可以是小数)
int 表示整数(必须是整数)
double 表示浮点数(既可以是整数,也可以是小数)
常用api
https://api.dart.cn/stable/dart-core/num-class.html
https://api.dart.cn/stable/dart-core/int-class.html
https://api.dart.cn/stable/dart-core/double-class.html
// 保留小数
print(3.1515926.toStringAsFixed(3));
// 返回余数
print(10.remainder(4));
// 数字比较 0相同 1 ,大于 ,-1 小于
print(10.compareTo(12));
//返回最大公约数
print(12.gcd(18));
// 科学计数法
print(1000.toStringAsExponential(2));
声明String类型
单引号 双引号
三引号可以声明包含换行符的字符串
常见api:
https://api.dart.cn/stable/dart-core/String-class.html
正则表达式:
RegExp(r'正则表达式');
RegExp(r'\d+');
demo:
String str3 = ''' console ''';
print(str3);
字符串拼接使用加号
print(""+"");
print("$str1 $str2");//模板字符串拼接
字符串分割:
print(str1.split(''));
字符串的裁接
print(" abc ".trim());
判断字符串是否为空(isEmpty是一个属性)
print('',isEmpty);
print('',isNotEmpty);
字符串替换 from是将要替换的内容,replace替换的新的内容
print(str1.replaceAll(from,replace));
也可以支持正则替换
print('h1h2'.replaceAll(RegExp(r'\d+'),"_"));
//通过正则匹配手机号
var isPhone = RegExp(r'^1\d{10}$')
print(isPhone.hasMatch('1333333333333'))
查找字符串
print(str1.contains('s'));
print(str1.indexOf('e'));//从左往右找
print(str1.lastIndexOf());//从右往左找
声明Boolean 类型
Dart 通过bool 关键字来表示布尔类型
布尔类型只有两个值 true 和false
对变量进行判断时,要显式地检查布尔值
dart里没有三个等号
var n1 = 0/0;
print(n1) NaN
可以使用 n1.isNaN 判断
List数据类型
dart中的数组,由List对象表示,list有两种声明方式
字面量方式
List list =[];//不限定元素的数据类型
List list = <int>[];//限定元素的数据类型是int
构造函数方式
List list = new List.empty(growable:true);//不限制长度的空列表(默认为false不能添加数据)
List list = new List.filled(3,0);//声明指定长度的填充列表填充3个0
扩展操作符(...)
var list = [1,2,3];
var list2 = [0,...list]; //[0,1,2,3]
常用api
https://api.dart.cn/stable/dart-core/List-class.html
var l6;
var l7 = [7,...?l6];//?避免警告的运算符号
print(l1.length);//长度
print(l1.reversed);//转换
print(l1.reversed。toList());//反转后的list
批量添加元素
l3.addAll([4,5,6]);
l3.remove(6);//删除元素
根据下标删除元素
l3.removeAt(index);
//指定位置添加元素
l3.insert(index,element)
清空
l3.clear();
合并元素
List words = ['Hello','World'];
print(words.join('-'));
便利List
forEach() 遍历列表
map() 便利并处理元素,然后生成新的列表
where() 返回满足条件的数据
any() 只要有一个项满足条件即返回true
every() 判断是否每一项都满足条件,都满足条件才返回true
for循环
for(var i = 0;i<nums.length;i++){
print(nums[i])
}
for in 循环
for(var item in nums){
print(item)
}
// 扩展
var pairs = [[1,2],[3,4]];
var flattened = pairs.expand((element)=>element).toList();
print(flattened);//[1,2,3,4]
//折叠(相当于js 的reduce)
int result = nums.fold(initialValue,(pre,element)=>{
return p* element;
})
print(result);
数据类型Set
Set是一个无序的,元素是唯一的集合
Set 有字面量和构造函数两种声明方式(字面量中用大括号)
无法通过下表取值
具有集合特有的操作
例如:求交集 并集 差集 等
常用api
https://api.dart.cn/stable/dart-core/Set-class.html
```text
var nums = <int>{1,2,2,3};//有重复的会自动去掉不会报错
print(nums);
//构造函数
var fruits = new Set();
fruits.add('香蕉');
fruits.add('苹果');
print(fruits);//{香蕉,苹果}
print(fruits.toList());//[香蕉,苹果]
List myNums = [1,2,2,3,4];
print(myNums.toSet());//{} // 可以将重复元素过滤掉
//集合特有的操作
var caocao = new Set();
caocao.addAll(['张辽', '司马懿']);
var liubei = new Set();
liubei.addAll('关羽','张飞');
求交集
print(caocao.intersection(liubei));//关羽
//并集
print(caocao.union(liubei));
//差集
print(caocao.difference(liubei));
//返回第一个元素
print(caocao.first);
//返回最后一个元素
print(caocao.last);
注意:集合不能通过下表取值
数据类型-map
map 是一个无需的键值对(key-value)映射。通常被称作 hash 或者字典
声明方式
var map = {key1:value,key2:value2};
var map = new Map();
map['key'] = value;
常用 api
https://api.dart.cn/stable/dart-core/Map-class.html
demo:
var person = {
'name':'张三',
}
var p = Map();
p['name'] = '李四';
print(p);
//访问
print(p['name']);
//判断 map 中的 key 是否存在
print(p.containsKey('name'));
print(p.containsValue());
//场景 如果 key 不存在我们就赋值,如果 key 已经存在则不赋值
p.putIfAbsent('gender',()=>'男');
获取 map 中所有的 key
print(p.keys);
获取 map 中所有的 value
print(p.values);
//根据条件进行删除
p.removeWhere((key,value)=>false);// 返回 true 就是删除
数据类型其他: 符文 Runes Runes 对象是 32 位字符对象,他可以把文字转换成符号表情或特定的文字 print('\u{1f44d}') =>符号表情 https://copychar.cc/
Symbol(反射) 在 Dart 中符号用#好开头来表示的标识符
dynamic 动态数据类型(比如声明变量既可以是数字也可以是字符串)
dart 中的字符串是用 utf-16 的字符集 print(str.length); print(str.runes.length);//通过 utf32 表示字符
Runes 可以将 utf-32 字符集表示的内容转换成符号 Runes input = new Runes('\u{1f680}'); print(new String.fromCharCodes(input));
//symbol 声明 var a = #abc; print(a);// Symbol("abc") var b = new Symbol('abc'); print(#abc == new Symbol('abc'));//true
//声明动态类型的变量 dynamic foo = 'bar'; print(foo); foo = 123; print(foo);
**运算符**
```Plain Text
地板除(~/) 对除法运算的结果做一个向下去整操作
类型判断运算符 (is|is!) 判断某一个变量属于某一个类型 !取非操作
避空运算符(??|??=) 如果变量为空我们才会对变量赋值,如果变量不为空不做任何操作
条件属性的访问(?.) 先判断属性是否存在 存在才访问
级联运算符(..)
demo: myObject.myMethod(); //返回的是myMethod的返回值
myObject..myMethod();//返回myObject对象的引用
//地板除
print(7~/4); // 1
//类型判断运算符
List list = [];
if(list is List){
print('list is List')
}
//避空运算符
print(1??3); //返回1
print(null ?? 12); //返回12
var foo;
print(foo ?? 0) //如果foo是null 则返回0
a??=3;
print(a); //3
//条件属性运算符(保护可能为空的属性)
var m = new Map();
print(m.length);//0
var obj;
print(obj.length);//警告
print(obj?.length);//优化
//级联运算符
Set s = new Set();
s..add('a')..add('b');
函数
声明函数 函数参数 作用域和闭包 异步函数
声明函数:
直接声明 Dart中声明函数不需要function 关键字
箭头函数(跟js类似但逻辑不一样)
Dart中箭头函数 函数体只能写一行且不能带结束的分号
Dart中的箭头函数,只是函数的一种简写方式
匿名函数
立即执行函数(跟js一样的)
//Dart中声明函数不需要function关键字
void printInfo(){
print('Hello,World');
}
void main(){
printInfo();
}
int getNum(){
return 'Hello';//这里会报错,返回值约定了int
}
返回值要与函数声明的类型要一致
//匿名函数
var myPrint = (value){
print(value);
};//这里要写分号
List fruits = ['苹果'];
fruits.forEach(myPrint);
//箭头函数
fruits.forEach((element)=>{
print(element) //这里不能写分号
});
//同上
fruits.forEach((element)=>element);
//立即执行函数
((int n){
print(n);
})(1)
函数参数
必填参数 参数类型 参数名称
可选参数 放在必填参数后面,通过中括号包裹起来,带默认值的可选参数
命名参数 用大括号包裹起来 调用函数时,命名参数的名称与声明函数中的名称保持一致
demo:
void main(){
//必填参数
//一个作用域范围内同一个方法不可以重名
String userInfo(String name){
return '你好:$name';
}
String res = userInfo("张三");
print(res);
//可选参数
String userInfo(String name,[dynamic age]){ //或者 [int age = 0];
return `你好:$name,年龄:$age`;
}
//命名参数 命名函数调用时,需要与声明时的形参一致
String userInfo(String name,{int age = 0}){}
String res = userInfo('张三',age:20);
//函数参数
var myPrint = (value){
print(value);
}
fruits.forEach(myPrint);//myPrint 为函数
}
作用域和闭包
作用域
void main(){//Global
funA(){
print();
}
}
内层可以访问外层的变量
闭包: Dart中闭包的实现与JavaScript中的完全一致
使用时机:既能重用变量,有能保护变量不被污染
实际原理:外层函数被调用后,外层函数的作用域对象(AO)被内层函数引用着,导致外层海曙的作用域对象无法释放,从而形成了闭包。
void main(){
parent(){
var money = 1000;
localNum--;
return(){
money -=100;
print(money);
}
}
}
异步函数
JavaScript 中,异步函数通过promise来实现的
async 函数返回一个Promise,await相当于等待promise
Dart中异步函数是通过Future来实现
async函数返回一个Future,await用于等待Future
Future 详情
https://api.dart.dev/stable/dart-async/Future-class.html
小知识:
https://httpbin.org/ip //返回一个ip地址
//https://pub.dev/packages/http
import 'package:http/http.dart' as http;
import 'dart:convert';//jsonDecode
Future getIPAddress(){
final url = 'https://httpbin.org/ip';
return http.get(url).then((response){
print(jsonDecode(response.body)['origin']);
})
}
void main(){
getIPAddress()
.then((ip)=>print(ip))
.catcheError((error)=>print(error));
}
pubspec.yaml 相当于package.json
pubspec.yaml内容:
name:dart
environment:
sdk:'>=2.7.0 < 3.0.0'
dependencies:
http:^0.12.2
Future getIPAddress()async{
final url = '';
final response = await http.get(url);
String ip = jsonDecode(response.body)['origin'];
return ip
}

类和对象
类 继承 抽象类 接口 混入 泛型 枚举
类:构造器(构造函数) 访问修饰 Getter和Setter 初始化列表 static 元数据
类简介:
类是通过class 声明的代码段,包含属性和方法
属性:用来描述类的变量
方法:类中的函数称为类的方法
对象是类的实例化结果(var obj = new MyClass());
编程方式:
面向对象编程(oop)
面向过程编程(pop)
//声明类
class Person{
//类属性
String name = '张三';
//类方法
void getInfo(){
print('我是 $name');
}
}
void main(){
//实例化类得到一个对象
Person p = new Person();
//访问类中的属性
print(p.name);
//访问类的方法
p.getInfo();
}
普通构造函数(构造器)
1.默认构造函数 与类名同名的函数,在实例化时,自动被调用
class Point{
num x;
num y;
// 同 num x,y;
//普通构造函数
Point(num x,num y){
//或者 Point(this.x,this.y)
print('我是默认构造函数 实例化时 会第一个被调用');
//this 可以省略
//当命名只想有歧义时,this不能省略,如果此作用域还有一个x或者y
this.x =0;
this.y = 0
}
}
new Point(1,2);
命名构造函数
在类中使用命名构造函器(类名.函数名)实现多个构造器,可以提供额外的清晰度
class Point{
num x,y;
Point.origin(){
x=0;
y=0;
}
Point.fromJson({x:0,y:0}){
this.x = x;
this.y = y;
}
}
void main(){
Point p1 = new Point.origin();
print(p1.x);
Point p2 = new Point.fromJson(x:6,y:6);
print(p2.x);
}
常量构造函数:如果类生成的对象不会改变,您可以通过常量构造函数使这些对象成为编译时常量
class Point{
num x;
num y;
Point(this.x,this.y);
}
void main(){
var p1 = new Point(1,2);
var p2 = new Point(1,2);
print(p1==p2) //false
}
//声明常量构造函数
class ImmutablePoint{
//属性必须通过final声明
final num x;
final num y;
//常量构造函数必须通过const声明 函数不能有body({})
const ImmutablePoint(this.x,this.y);
}
//常量构造函数,可以当作普通构造函数使用(但是失去了常量特性)
var p3 = new ImmutablePoint(1,2);
var p4 = new ImmutablePoint(1,2);
print(p1==p2);//false
//声明不可变对象,必须通过const关键字
var p5 = const ImmutablePoint(1,2);
var p6 = const ImmutablePoint(1,2);
print(p5==p6); //true
//默认关键字new
var p7 = ImmutablePoint(1,2);
var p8 = ImmutablePoint(1,2);
print(p7==p8);//false
工厂构造函数 通过facory声明,工厂函数不会自动生成实例,而是通过代码来决定返回的实例
class Person{//相当于单例
String name;
static Person instance;
//工厂构造函数
factory Person([String name = '刘备']){
//工厂构造函数中不能使用this关键字
//print(this.name); //这里会异常 不能使用this
if(Person.instance==null){
Person.instance = new Person.newSelf(name);
}
return Person.instance;
}
Person.newSelf(this.name);
}
访问修饰符
Dart与TypeScript不同,没有访问修饰符(public,protected,private)
Dart类中,默认的访问修饰符是公开的(即public)
如果属性或者方法以_(下划线)开头,则表示私有的(即private)
只有把类单独抽离出去,私有属性和方法才会起作用
lib/Person.dart
import 'lib/Person.dart'
class Person{
String name;
//声明私有的属性
num _money = 100;
Person(this.name);
num getMoney(){
return this._money;
}
}
Getter与Setter
Getter(获取器)是通过get关键字修饰的方法
函数没有小括号,访问时也没有小括号(像访问属性一样访问方法)
Setter(修改器) 是通过set关键字修饰的方法
访问时,像设置属性一样给函数传参
class Circle{
final double PI = 3.1415926;
num r;
Circle(this.r);
// 使用get 声明的方法不能有小括号
num get area{
return this.PI * this.r * ths.r
}
//Setter
set setR(){
this.r = value;
}
}
void main(){
var c = new Circle(10);
//通过Setter 修改属性
c.setR=20;
print(c.area);
}
初始化列表
作用:在构造函数中设置属性的默认值
时机:在构造函数体执行之前执行
语法:在都好分隔初始化表达式
场景:常用于设置final常量的值
class Rect{
int height;
int width;
//Rect([int height =2,int width=10]){} //也可以用可选参数实现
//Rect({int height =2,int width=10}){} //也可以用可选参数实现
Rect():height=2,width=10{
//用到点都需要用${}访问
print('${this.height}--${this.width}')
}
//初始化列表的特殊用法(重定向构造函数)
Rect.twoD(height):this(height,0);
}
static
static关键字用来指定静态成员
通过static修饰的属性是静态属性
通过static修饰的方法为静态方法
静态成员可以通过类名称直接访问(不需要实例化)
实例化是比较消耗资源的,声明静态成员,可以提高程序性能。
注意事项:
静态方法不能访问非静态成员,非静态方法可以访问静态成员
静态方法中不能使用this关键字
不能使用this关键字,访问静态属性
class Person{
static String name = '张三';
int age = 18;
//写了void为没有值返回,如果不写默认返回的是null
void printInfo(){
print(this.name); //这里不能通过this关键字,访问静态属性
print(name);//可以这样直接访问
//非静态方法 可以访问静态方法
printInfo2();
}
static printInfo2(){
//静态方法不能访问非静态属性
print(age);//这里会报错
}
}
void main(){
//静态成员,可以通过类名直接访问
print(Person.name);
//不能通过实例化对象访问静态属性
var p = new Person();
print(p.name);
}

元数据
元数据
元数据以@开头,可以给代码标记一些额外的信息元数据可以用来库,类,构造器,函数,字段,参数或变量声明的前面@override(重写)某方法添加该注解后,表示重写了父类中的同名方法
@required(必填)可以通过@required来注解Dart中的命名参数,用来指示他是必填参数
@deprecated(弃用)若某类或某方法加上该注解之后,表示此方法或类不再建议使用
class Phone{
//旧版本中的方法 会在将来的版本中移除
@deprecated
activate(){
turnOn();
}
turnOn(){
print('开机');
}
}
继承
- 根据类的先后顺序,可以将类丰城父类和子类
- 子类通过 extends 关键字继承父类
- 继承后,子类可以使用父类中可见的内容(属性或方法)
- 子类中,可以通过@override 元数据来标记复写方法
- 复写方法:子类中与父类中同名的方法
- 子类中,可以通过 super 关键字来引用父类中,可见的内容
- 属性
- 方法(普通构造函数,命名构造函数)
class Father{
String name = '刘备';
num money = 1000;
say(){
print('我是$name')
}
Father.origin(job){
}
}
class Son extends Father{
String name = '小刘';
@override //表示覆写 写不写都行官方建议写
say(){
super.say();//访问父类的方法
print('我是$name 我爹是${super.name}');
}
//通过super继承父类的普通构造函数
//Son(String job) :super(job);//传到父级中的构造
//继承命名构造函数
Son(String job):super.origin(job);
}
抽象类
- 抽象类是用 abstract 关键字修饰的类
- 抽象类的作用是充当普通类的模板,约定一些必要的属性和方法
- 抽象方法是指没有方法体的方法
- 抽象类中一般都有抽象方法,也可以没有抽象方法
- 普通类中,不能有抽象方法
- 抽象类不能被实例化(不能被 new)
- 抽象类可以被普通类继承(extends)
- 如果普通类继承抽象类,必须实现抽象类中的所有抽象方法
- 抽象类还可以充当接口被实现(implements)
- 如果把抽象类当作接口实现的话,普通类必须的实现抽象类里定义的所有属性和方法
//抽象类必须通过abstract 关键字声明
//抽象类中可以有抽象方法,也可以没有抽象方法,一般来说抽象类都有抽象方法
abstract class Phone{
//声明抽象方法
void processor();//手机的处理器
void camera(); //手机摄像头
void info(){}//抽象类中普通方法
}
class Xiaomi extends Phone{
//普通类继承了抽象类就必须实现抽象类中所有的抽象方法
@override
void processor(){
print('晓龙888');
}
@override
void camera(){
print('三星摄像头')
}
//普通类中不能有抽象方法
void aaa();
}
接口
- 接口在 Dart 中就是一个类(只是用法不一样)
- 与 java 不同,java 中的接口需要 interface 关键字声明;Dart 中不需要
- 接口可以是任意类,但一般使用抽象类做接口
- 一个类可以实现(implements)多个接口,多个接口用逗号分隔
- class MyClass implements Interface1,Interface2{...}
- 接口可以堪称一个个小零件,类实现接口就相当于组装零件
- 普通类实现接口后,必须重写接口中所有的属性和方法
//手机处理器
abstract class Processor{
String cores;//内核数
arch(String name);//芯片制程 7nm 5nm
}
abstract class Camera{
String resolution;//分辨率
brand(String name);//品牌
}
//通过普通类实现接口
class Phone implements Processor, Camera{
@override
String cores;
@override
String resolution;
Phone(this.cores,this.resolution);
@override
arch(String name){
print('芯片制程'+name);
}
@override
brand(String name){
print('相机品牌'+name)
}
}
void main(){
}
混入
- 混入(Mixin)是一段公共代码,混入有两种声明方式:
- 将类当作混入 class MixinA{...}
- 作为 Mixin 的类只能继承自 Object,不能继承其他类
- 作为 Mixin 的类不能有构造函数
- 使用 mixin 关键字声明 mixin MixinB{...}
- 将类当作混入 class MixinA{...}
- 混入(Mixin)可以提高代码复用的效率,普通类可以通过 with 来使用混入
- class MyClass with MixinA,MixinB{...}
- 使用多个混入时,后引入的混入会覆盖之前混入中的重复的内容
- MixinA 和 Mixin 中都有 hello()方法,MyClass 会使用 MixinB 中的
class MixinA{
String name = 'MixinA';
void printA(){
print('A');
}
}
class MixinB{
String name = 'MixinB';
void printB(){
print('B');
}
}
class MyClass with MixinA,MixinB{
}
泛型
- 泛型是在函数 类 接口中指定宽泛数据类型的语法
- 泛型函数
- 泛型类
- 泛型接口
- 通常,在尖括号中,使用一个字母来表示类型,例如 E T S K 和 V 等
返回类型 函数名 <输入类型>(参数类型 参数){
函数体
}
T getData<T>(T value){
return value;
}
- 作用:使用泛型可以减少重复的代码
泛型函数
T getData <T>(T value){
return value;
}
//只约定参数类型,不约定函数的返回值的类型
getData2 <T>(T value){
return value;
}
void main(){
print(getData<int>(20));
print(getData<String>('20'));
}
泛型类
class CommonClass<T>{
Set s = new Set<T>();
void add(T value){
this.s.add(value);
}
void info(){
print(this.s)
}
}
void main(){
CommonClass = new CommonClass<int>();
c.add(1);
c.info();
}
//字面量形式的泛型
Set s = <int>{};
s.add(1);
s.add(3);
print(s);
泛型接口
abstract class ObjectCache{
getBykey(String key);
void setByKdy(String key,Object value);
}
abstract class StringCache{
getBykey(String key);
void setByKdy(String key,String value);
}
//泛型接口
abstract class Cache<T>{
getBykey(String key);
void setByKey(String key,T value);
}
//文件缓存(先把T给FileCache)
class FileCache<T> implements Cache<T>{
@override
getBykdy(String key){
return null;
}
@override
void setByKey(String key,T value){
print('文件缓存 key = ${key} value = ${value}');
}
}
void main(){
//文件缓存 缓存字符串
FileCache fc = new FileCache<String>();
fc.setByKey('foo','bar');
}
泛型限制参数类型
class SomeBaseClass{
//...
}
class Foo<T extends SomeBaseClass>{
String toString()=>"Instance of 'Foo<$T>'"
}
class AnotherClass{
}
void main(){
var someBaseClassFoo = Foo<SomeBaseClass>();
print(someBaseClassFoo);
//这里会报错类型已经限制
var someBaseClassFoo = Foo<AnotherClass>();
print(someBaseClassFoo);
}
枚举
- 枚举是数量固定的常量值,通过 enum 关键字声明
- enum Color{red,green,blue}
- 枚举的 values 常量,可以获取所有枚举值列表
- List<Color> colors = Color.valuds;
- 可以根据 index 获取值的索引
- assert(Color.green.index==1)
enum Color{red,green,blue}
void main(){
//通过index返回枚举中具体常量的值
print(Color.green.index);
//通过valud 返回常量列表
print(Color.valuds);
List<Color> colors = Color.values;
print(colors);
//通过下标访问列表中的内容
print(colors[0])
//通过forEach 去便利列表的内容
color.forEach((element){
print('value: $element,index:${element.index}');
})
}
库生态
- Dart 中的库就是具有特定功能的模块
- 可能包含单个文件,也可能包含多个文件
- 按照库的作者进行划分,库可以分成三类
- 自定义库(工程师自己写的)
- 系统库(Dart 中自带的)
- 第三方库(Dart 生态中的)
- Dart 生态
- https://pub.dev/
- pub 命令(D:\flutter\bin\cache\dart-sdk\bin)

自定义库
自定义库-通过 library 来声明库
- 每个 Dart 文件默认都是一个库,只是没有使用 library 来显示声明
- Dart 使用_(下划线)开头的标识符,表示库内访问可见(私有)
- library 关键字声明的库名称建议使用:小写字母+下划线
// main.dart
main(){
print('Hello World');
}
//main.dart
library main;//默认颖仓了一个main的library的声明
main(){
print('Hello World');
}
自定义库-通过 import 来引入库
- 不同类型的库,映入方式不同
- 自定义库(import '库的位置/库名称.dart')
//文件 lib/MyCustom.dart
library MyCustom; //默认省略的 建议写成my_custom
class MyCustom{
String name = 'MyCustom';
static num version = 1.8;
void info(){
print('我是自定义库');
}
}
import 'lib/MyCustom.dart';
void main(){
MyCustom mc = new MyCustom();
mc.info();
print(MyCustom.version)
}
- 系统库(import 'dart:库名称')
import 'dart:math';
import 'dart:core';//默认引入的库
void main(){
print(pi)
print(min(3,6));
print(max(3,6));
}
- 第三方库
引入部分库(进引入部分内容(按需加载))
- 包含引入(show)
- 排除引入(hide)
void f1(){
print('f1 is running');
}
void f2(){
print('f2 is running');
}
void f3(){
print('f3 is running');
}
import 'lib/common.dart' show f1,f3;// 引入指定的方法
void main(){
f1();
f3();
}
引入冲突处理
- 指定库的前缀
- 当命名冲突时,可以通过 as 关键字,给库声明一个前缀
import 'lib/common.dart';
import 'lib/function.dart' as func; //给库添加前缀,解决命名冲突问题
void main(){
func.f1();
}
延迟引入(懒加载)
- 使用 deferred as 关键字来标识需要延时加载的库
import 'lib/function.dart' deferred as func;
void main(){
func.hello();//这里会报错无法使用
}
Future greet()async {
await func.loadLibrary();//返回的是future
func.hello();
}
part 喝 part of 来组装库

系统库
- 系统库(也叫核心库)是 Dart 提供的常用内置库
- 不需要单独下载,就可以直接使用
- 引入
- import 'dart:库名';
- import 'dart:core';//会自动引入(无需手动引入)
- 系统库列表
第三方库
来源
使用
- 在项目目录下创建 pubspec.yaml
- 在 pubspec.yaml 中声明第三方库(依赖)
- 命令行中进入 pubspec.yaml 所在目录,执行 pub get 进行安装
- 项目中引入已安装的第三方库(import 'package:xxxx/xxx.dart';)
第三方库接口

pubspec.yaml
官网:
https://flutter.dev
github
https://github.com/flutter/flutter
中文网
https://flutterchina.club/
https://flutter.cn/
git:
flutter 开发需要 git 支持
下载: https://git-scm.com/download
git --version


