要在我们本地开发Dart程序的话首先需要安装Dart Sdk
官方文档:https://dart.dev/get-dart
http://www.gekorm.com/dart-windows/
如果mac电脑没有安装brew这个工具首先第一步需要安装它: https://brew.sh/
brew tap dart-lang/dart
brew install dart
Dart的开发工具有很多: IntelliJ IDEA 、 WebStorm、 Atom、Vscode等
在Vscode中配置Dart:
1、找到vscode插件安装dart
2、找到vscode插件安装code runner Code Runner 可以运行我们的文件
## 入口方法
// void 表示main方法没有返回值
void main(){
print('你好dart');
}
dart是一个强大的脚本类语言,可以不预先定义变量类型 ,自动会类型推导
dart中定义变量可以通过var关键字可以通过类型来申明变量
var str='this is var';
String str='this is var'; // 字符串
int str=123; // 数字
// 注意: var 后就不要写类型 , 写了类型 不要var 两者都写 var a int = 5; 报错
## 常量 final 和 const 修饰符
const:值不变 一开始就得赋值
final: 可以开始不赋值 只能赋一次 ; 而final不仅有const的编译时常量的特性,最重要的它是运行时常量,并且final是惰性初始化,即在运行时第一次使用前才初始化
永远不改量的量,请使用final或const修饰它,而不是使用var或其他变量类型。
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
const bar = 1000000; // Unit of pressure (dynes/cm2)
const double atm = 1.01325 * bar; // Standard atmosphere
## 命名规则
1. 变量名称必须由数字、字母、下划线和美元符($)组成。
2. 标识符开头不能是数字
3. 标识符不能是保留字和关键字。
4. 变量的名字是区分大小写的如: age和Age是不同的变量。在实际的运用中,也建议,不要用一个单词大小写区分两个变量。
5. 标识符(变量名称)一定要见名思意 :变量名称建议用名词,方法名称建议用动词
字符串定义:
var str1='this is str1';
String str1='this is str1';
String str1='''this is str1
this is str1
this is str1
''';
String str1="""
this is str1
this is str1
this is str1
""";
字符串拼接
String str1='你好';
String str2='Dart';
print("$str1 $str2"); // $ 符号拼接
print(str1 + str2); // + 号拼接
//1、int 必须是整型
int a=123;
//2、double 既可以是整型 也可是浮点型
double b=23.5;
double b=24;
bool flag1=true;
bool flag2=false;
// 1、第一种定义List的方式
var l1 = ["张三",20,true];
print(l1); // [张三, 20, true]
print(l1.length); // 3
print(l1[0]); // 张三
print(l1[1]); // 0
// 2、第二种定义List的方式 指定类型
var l2 = <String>["张三","李四"];
print(l2);
var l3 = <int>[12, 30];
print(l3);
// 3、第三种定义List的方式
// 增加数据: 通过[]创建的集合它的容量可以变化
var l4 = [];
print(l4);
print(l4.length);
l4.add("张三");
l4.add("李四");
l4.add(20);
print(l4);
print(l4.length);
// 4、第四种定义List的方式
var l6=new List(); // 在新版本的dart里面没法使用这个方法了
var l6=List.filled(2, ""); // 创建一个固定长度的集合
print(l6);
print(l6[0]);
l6[0]="张三"; // 修改集合的内容
l6[1]="李四";
print(l6); // [张三, 李四]
l6.add("王五"); // 报错:超出长度
//通过List.filled创建的集合长度是固定
var l6=List.filled(2, "");
print(l6.length);
l6.length=0; //修改集合的长度 报错
var l7=<String>["张三","李四"];
print(l7.length); //2
l7.length=0; // 可以改变的
print(l7); // []
var l8=List<String>.filled(2, "");
l8[0]="string";
print(l8);
//第一种定义 Maps的方式
var person={
"name":"张三",
"age":20,
"work":["程序员","送外卖"]
};
print(person);
print(person["name"]); // 张三
print(person["age"]); // 20
print(person["work"]); // ["程序员","送外卖"]
//第二种定义 Maps的方式
var p=new Map();
p["name"]="李四";
p["age"]=22;
p["work"]=["程序员","送外卖"];
print(p);
print(p["age"]); // 22
// is 关键词判断类型
var str=123;
if(str is String){
print('是string类型');
}else if(str is int){
print('int');
}else{
print('其他类型');
}
int a=13;
int b=5;
print(a + b); // 加
print(a - b); // 减
print(a * b); // 乘
print(a / b); // 除
print(a % b); // 取余
print(a ~/ b); // 取整
// ++ 自增
// -- 自减
// 在赋值运算里面 如果++ -- 写在前面 这时候先运算 再赋值,如果++ --写在后面 先赋值后运行运算
var a = 10;
var b = a--;
print(a); // 9
print(b); // 10
int a=5;
int b=3;
print(a == b); // 判断是否相等
print(a != b); // 判断是否不等
print(a > b); // 判断是否大于
print(a < b); // 判断是否小于
print(a >= b); // 判断是否大于等于
print(a <= b); // 判断是否小于等于
/* ! 取反 */
bool flag=false;
print(!flag); // 取反
/* &&并且:全部为true的话值为true 否则值为false */
bool a=true;
bool b=true;
print(a && b);
/* ||或者:全为false的话值为false 否则值为true */
bool a=false;
bool b=false;
print(a || b);
// 1、基础赋值运算符 = ??=
int a = 10;
int b = 3;
print(a);
int c = a+b; //从右向左
// b??=23; 表示如果b为空的话把 23赋值给b
int b = 6;
b ??= 23;
print(b); // 23
int b;
b ??= 23;
print(b); // 23
// 2、 复合赋值运算符 += -= *= /= %= ~/=
var a = 13;
a += 10; //表示a=a+10
print(a);
var a = 4;
a *= 3; // a= a*3;
print(a);
// 其余符号类推
// 1、if else switch case
bool flag=true;
if(flag){
print('true');
}else{
print('false');
}
// if else 方式
var score = 41;
if (score > 90) {
print('优秀');
} else if (score > 70) {
print('良好');
} else if (score >= 60) {
print('及格');
} else {
print('不及格');
}
// switch case 方式
var sex = "女";
switch (sex) {
case "男":
print('性别是男');
break;
case "女":
print('性别是女');
break;
default:
print('传入参数错误');
break;
}
// 2、三目运算符
bool flag=false;
String c = flag ? '我是true' : '我是false';
print(c);
// 3、??运算符
var a;
var b = a ?? 10;
print(b); // 10
var a=22;
var b= a ?? 10;
print(b); // 22
Number与String类型之间的转换
// 1. Number与String类型之间的转换
// String类型转成Number类型
// int.parse()
String str = '123';
var myNum = int.parse(str);
print(myNum is int); // true
// double.parse()
String str = '123.1';
var myNum = double.parse(str);
print(myNum is double); // true
String price = '12';
var myNum = double.parse(price);
print(myNum); // 12.0
print(myNum is double); // true
String price = '';
var myNum = double.parse(price);
print(myNum); //
print(myNum is double); // 报错
// 运用 try ... catch 保证程序正常运行
String price = '';
try {
var myNum = double.parse(price);
print(myNum);
} catch (err) {
print(0);
}
// Number类型转换成String类型 toString()
var myNum = 12;
var str = myNum.toString();
print(str is String); // true
其他类型转换成Booleans类型
// isEmpty:判断字符串是否为空
var str = '';
if (str.isEmpty) {
print('str空');
} else {
print('str不为空');
}
// 判断是否向相等
var myNum = 123;
if(myNum == 0){
print('0');
}else{
print('非0');
}
// isNan: 判断是否为 NaN
var myNum = 0 / 0;
print(myNum);
if (myNum.isNaN) {
print('NaN');
}
for (int i = 1; i <= 100; i++) {
print(i);
}
//第一步,声明变量int i = 1;
//第二步,判断i <=100
//第三步,print(i);
//第四步,i++
//第五步 从第二步再来,直到判断为false
// while 循环
// while(表达式/循环条件) {语句/循环体}
int i = 1;
var sum = 0;
while (i <= 100) {
sum += i;
i++;
}
print(sum); // 5050
// do while 循环
// do {语句/循环体} while(表达式/循环条件);
int i = 1;
var sum = 0;
do {
sum += i;
i++;
} while (i <= 100);
print(sum); // 5050
// while 和 do while的区别:
// 第一次循环条件不成立的情况下 仍会执行一次 do 里面的代码
/*
break语句功能:
1、在switch语句中使流程跳出switch结构。
2、在循环语句中使流程跳出当前循环,遇到break 循环终止,后面代码也不会执行
3、如果在循环中已经执行了break语句,就不会执行循环体中位于break后的语句。
4、在多层循环中,一个break语句只能向外跳出一层
5、break可以用在switch case中 也可以用在 for 循环和 while循环中
continue语句的功能:
1、只能在循环语句中使用,使本次循环结束,即跳过循环体重下面尚未执行的语句,接着进行下次的是否执行循环的判断。
2、continue可以用在for循环以及 while循环中,但是不建议用在while循环中,不小心容易死循环
*/
常用属性:
length 长度
reversed 翻转
isEmpty 是否为空
isNotEmpty 是否不为空
常用方法:
add 增加
addAll 拼接数组
indexOf 查找 传入具体值
remove 删除 传入具体值
removeAt 删除 传入索引值
fillRange 修改
insert(index,value); 指定位置插入
insertAll(index,list) 指定位置插入List
toList() 其他类型转换成List
join() List转换成字符串
split() 字符串转化成List
forEach
map
where
any
every
常用属性:
keys 获取所有的key值
values 获取所有的value值
isEmpty 是否为空
isNotEmpty 是否不为空
常用方法:
remove(key) 删除指定key的数据
addAll({...}) 合并映射 给映射内增加属性
containsValue 查看映射内的值是否有传入的参数 返回true/false
forEach
map
where
any
every
print()
/*
基本格式:
返回类型 方法名称(参数1,参数2,...){
方法体
return 返回值;
}
*/
void printInfo(){
print('我是一个自定义方法');
}
必传参数
// 定义一个方法 求1到这个数的所有数的和
String printUserInfo(String username, int age) {
//行参
return "姓名:$username---年龄:$age";
}
print(printUserInfo('张三', 20)); //实参
可选参数
// 定义一个带可选参数的方法 ,最新的dart定义可选参数需要指定类型默认值
String printUserInfo(String username, [int age = 0]) { //行参
if (age != 0) {
return "姓名:$username---年龄:$age";
}
return "姓名:$username---年龄保密";
}
print(printUserInfo('张三', 21)); // 姓名:张三---年龄:21
print(printUserInfo('张三')); // 姓名:张三---年龄保密
默认参数
String printUserInfo(String username, [String sex = '男', int age = 0]) {
if (age != 0) {
return "姓名:$username---性别:$sex--年龄:$age";
}
return "姓名:$username---性别:$sex--年龄保密";
}
print(printUserInfo('张三')); // 姓名:张三---性别:男--年龄保密
print(printUserInfo('小李', '女')); // 姓名:小李---性别:女--年龄保密
print(printUserInfo('小李', '女', 30)); // 姓名:小李---性别:女--年龄:30
命名参数
String printUserInfo(String username, {int age = 0, String sex = '男'}) {
if (age != 0) {
return "姓名:$username---性别:$sex--年龄:$age";
}
return "姓名:$username---性别:$sex--年龄保密";
}
print(printUserInfo('张三', age: 20, sex: '未知')); // 姓名:张三---性别:未知--年龄:20
var printNum = (int n) {
print(n + 2);
};
printNum(12);
((int n) {
print(n);
print('我是自执行方法');
})(12);
递归
var sum = 1;
fn(int n) {
sum *= n;
if (n == 1) {
return;
}
fn(n - 1);
}
fn(100);
print(sum); // 5050
闭包
/*
闭包:
1、全局变量特点: 全局变量常驻内存、全局变量污染全局
2、局部变量的特点: 不常驻内存会被垃圾机制回收、不会污染全局
/* 想实现的功能:
1.常驻内存
2.不污染全局
产生了闭包,闭包可以解决这个问题.....
闭包: 函数嵌套函数, 内部函数会调用外部函数的变量或参数, 变量或参数不会被系统回收(不会释放内存)
闭包的写法: 函数嵌套函数,并return 里面的函数,这样就形成了闭包。
*/
*/
fn() {
var a = 123; /*不会污染全局 常驻内存*/
return () {
a++;
print(a);
};
}
var b = fn();
b(); // 124
b(); // 125
b(); // 126
面向对象编程(OOP)的三个基本特征是:封装、继承、多态
封装:封装是对象和类概念的主要特性。封装,把客观事物封装成抽象的类,并且把自己的部分属性和方法提供给其他对象调用, 而一部分属性和方法则隐藏。
继承:面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
多态:允许将子类类型的指针赋值给父类类型的指针, 同一个函数调用会有不同的执行效果 。
Dart所有的东西都是对象,所有的对象都继承自Object类。
Dart是一门使用类和单继承的面向对象语言,所有的对象都是类的实例,并且所有的类都是Object的子类
一个类通常由属性和方法组成。
class Person {
String name = "张三";
int age = 23;
void getInfo() {
// print("$name----$age");
print("${this.name}----${this.age}");
}
void setInfo(int age) {
this.age = age;
}
}
void main() {
//实例化
Person p1 = new Person();
print(p1.name); // 张三
p1.setInfo(28);
p1.getInfo(); // 张三----28
}
class Person {
String name = '张三';
int age = 20;
//默认构造函数
Person() {
print('这是构造函数里面的内容 这个方法在实例化的时候触发');
}
void printInfo() {
print("${this.name}----${this.age}");
}
}
// 最新版本的dart中需要初始化不可为null的实例字段,如果不初始化的话需要在属性前面加上late
class Person {
late String name;
late int age;
//默认构造函数的简写
Person(this.name, this.age);
void printInfo() {
print("${this.name}----${this.age}");
}
}
void main() {
Person p1 = new Person('张三', 20);
p1.printInfo(); // 张三----20
Person p2 = new Person('李四', 25);
p2.printInfo(); // 李四----25
}
class Person {
late String name;
late int age;
// 默认构造函数的简写
Person(this.name, this.age);
// 命名构造函数
Person.now() {
print('我是命名构造函数');
}
// 可写多个
Person.setInfo(String name, int age) {
this.name = name;
this.age = age;
}
void printInfo() {
print("${this.name}----${this.age}");
}
}
void main() {
Person p1=new Person('张三', 20); // 默认实例化类的时候调用的是 默认构造函数
Person p1=new Person.now(); // 命名构造函数
Person p1 = new Person.setInfo('李四', 30);
p1.printInfo(); // 李四----30
}
class Animal{
late String _name; // _定义私有属性
late int age;
//默认构造函数的简写
Animal(this._name,this.age);
void printInfo(){
print("${this._name}----${this.age}");
}
String getName(){
return this._name;
}
void _run(){
print('这是一个私有方法');
}
execRun(){
this._run(); // 类里面方法的相互调用
}
}
getter 和 setter 修饰符
class Rect{
late num height;
late num width;
Rect(this.height,this.width);
// getter
get area{
return this.height*this.width;
}
// setter
set areaHeight(value){
this.height=value;
}
}
void main(){
Rect r = new Rect(10,4);
r.areaHeight = 6; // 调用setter
print(r.area); // 调用getter
}
/*
Dart中的静态成员:
1、使用static 关键字来定义静态的变量和函数
2、静态方法不能访问非静态成员,非静态方法可以访问静态成员
*/
class Person {
static String name = '张三';
int age=20;
static void show() {
print(name);
}
void printInfo(){ /*非静态方法可以访问静态成员以及非静态成员*/
print(name); //访问静态属性
print(this.age); //访问非静态属性
show(); //调用静态方法
}
static void printUserInfo(){//静态方法
print(name); //静态属性
show(); //静态方法
}
}
as 类型转换
class Person {
String name;
num age;
Person(this.name, this.age);
void printInfo() {
print("${this.name}---${this.age}");
}
}
var p1;
p1 = new Person('张三1', 20);
(p1 as Person).printInfo(); // 感觉很鸡肋
is 类型判断
class Person {
String name;
num age;
Person(this.name, this.age);
void printInfo() {
print("${this.name}---${this.age}");
}
}
Person p = new Person('张三', 20);
if (p is Person) {
p.name = "李四";
}
p.printInfo(); // 李四---20
print(p is Object); // true
… 级联操作 (连缀)
class Person {
String name;
num age;
Person(this.name, this.age);
void printInfo() {
print("${this.name}---${this.age}");
}
}
Person p1 = new Person('张三1', 20);
p1.printInfo(); // 张三1---20
p1
..name = "李四"
..age = 30
..printInfo(); // 李四---30
1、子类使用extends关键词来继承父类
2、子类会继承父类里面可见的属性和方法 但是不会继承构造函数
3、子类能复写父类的方法、 getter和setter
class Person {
String name='张三';
num age=20;
void printInfo() {
print("${this.name}---${this.age}");
}
}
class Web extends Person{
}
main(){
Web w=new Web();
print(w.name); // 张三
w.printInfo(); // 张三---20
}
实例化子类给父类传参
class Person {
String name;
num age;
Person(this.name, this.age);
void printInfo() {
print("${this.name}---${this.age}");
}
}
class Web extends Person {
late String sex;
Web(String name, num age, String sex) : super(name, age) { // 通过调用 super 方法
this.sex = sex;
}
run() {
print("${this.name}---${this.age}--${this.sex}");
}
}
main() {
Web w = new Web('张三', 12, "男");
w.printInfo();
w.run();
}
实例化子类给父类命名构造函数传参
class Person {
String name;
num age;
Person(this.name, this.age);
Person.xxx(this.name, this.age);
void printInfo() {
print("${this.name}---${this.age}");
}
}
class Web extends Person {
late String sex;
Web(String name, num age, String sex) : super.xxx(name, age) { // 通过调用 super.XXX 方法
this.sex = sex;
}
run() {
print("${this.name}---${this.age}--${this.sex}");
}
}
main() {
Web w = new Web('张三', 12, "男");
w.printInfo();
w.run();
}
子类覆写父类方法
class Person {
String name;
num age;
Person(this.name,this.age);
void printInfo() {
print("${this.name}---${this.age}");
}
work(){
print("${this.name}在工作...");
}
}
class Web extends Person{
Web(String name, num age) : super(name, age);
run(){
print('run');
}
// 覆写父类的方法
@override // 可以写也可以不写 建议在覆写父类方法的时候加上 @override
void printInfo(){
print("姓名:${this.name}---年龄:${this.age}");
}
@override
work(){
print("${this.name}的工作是写代码");
}
}
子类调用父类的方法
class Person {
String name;
num age;
Person(this.name,this.age);
void printInfo() {
print("${this.name}---${this.age}");
}
work(){
print("${this.name}在工作...");
}
}
class Web extends Person{
Web(String name, num age) : super(name, age);
run(){
print('run');
super.work(); // 子类调用父类的方法 通过 super
}
//覆写父类的方法
@override //可以写也可以不写 建议在覆写父类方法的时候加上 @override
void printInfo(){
print("姓名:${this.name}---年龄:${this.age}");
}
}
main(){
Web w=new Web('李四',20);
w.run();
}
Dart抽象类主要用于定义标准,子类可以继承抽象类,也可以实现抽象类接口。
1、抽象类通过abstract 关键字来定义
2、Dart中的抽象方法不能用abstract声明,Dart中没有方法体的方法我们称为抽象方法。
3、如果子类继承抽象类必须得实现里面的抽象方法
4、如果把抽象类当做接口实现的话必须得实现抽象类里面定义的所有属性和方法。
5、抽象类不能被实例化,只有继承它的子类可以
// 定义一个抽象类
abstract class Animal {
eat(); //抽象方法
run(); //抽象方法
printInfo() {
print('我是一个抽象类里面的普通方法');
}
}
// 继承抽象类
class Dog extends Animal {
@override
eat() {
print('小狗在吃骨头');
}
@override
run() {
// TODO: implement run
print('小狗在跑');
}
}
class Cat extends Animal {
@override
eat() {
// TODO: implement eat
print('小猫在吃老鼠');
}
@override
run() {
// TODO: implement run
print('小猫在跑');
}
}
main() {
Dog d = new Dog();
d.eat();
d.printInfo();
Cat c = new Cat();
c.eat();
c.printInfo();
// Animal a=new Animal(); // 抽象类没法直接被实例化
}
extends抽象类 和 implements的区别:
1、如果要复用抽象类里面的方法,并且要用抽象方法约束子类的话我们就用extends继承抽象类
2、如果只是把抽象类当做标准的话我们就用implements实现抽象类
1、dart 的接口没有 interface 关键字定义接口,而是普通类或抽象类都可以作为接口被实现。
2、使用 implements 关键字进行实现。
3、但是 dart 的接口有点奇怪,如果实现的类是普通类,会将普通类和抽象中的属性的方法全部需要覆写一遍。
4、因为抽象类可以定义抽象方法,普通类不可以,所以一般如果要实现像Java接口那样的方式,一般会使用抽象类。
5、建议使用抽象类定义接口。
abstract class Db {
//当做接口 接口:就是约定 、规范
late String uri; // 数据库的链接地址
add(String data);
save();
delete();
}
class MsSql implements Db { // 使用 implements 关键字继承接口
@override
late String uri;
@override
add(String data) {
print('这是mssql的add方法' + data);
}
@override
delete() {
// TODO: implement delete
return null;
}
@override
save() {
// TODO: implement save
return null;
}
}
main() {
Mysql mysql = new Mysql('xxxxxx');
mysql.add('1243214');
}
一个类可以实现多个接口
// 定义接口 A
abstract class A {
late String name;
printA();
}
// 定义接口 B
abstract class B {
printB();
}
// 同时实现 A B 两个接口
class C implements A, B {
@override
late String name;
@override
printA() {
print('printA');
}
@override
printB() {
// TODO: implement printB
return null;
}
}
void main() {
C c = new C();
c.printA();
}
mixins的中文意思是混入,就是在类中混入其他功能。
在Dart中可以使用mixins实现类似多继承的功能
因为mixins使用的条件,随着Dart版本一直在变,这里讲的是Dart2.x中使用mixins的条件:
1、作为mixins的类只能继承自Object,不能继承其他类
2、作为mixins的类不能有构造函数
3、一个类可以mixins多个mixins类
4、mixins绝不是继承,也不是接口,而是一种全新的特性
// 定义 mixins A
class A {
String info = "this is A";
void printA() {
print("A");
}
}
// 定义 mixins B
class B {
void printB() {
print("B");
}
}
// 定义类 C mixins A 和 B
class C with A, B {}
void main() {
var c = new C();
c.printA();
c.printB();
print(c.info);
}
// 定义一个父类
class Person {
String name;
num age;
Person(this.name, this.age);
printInfo() {
print('${this.name}----${this.age}');
}
void run() {
print("Person Run");
}
}
// 定义一个 mixins A
class A {
String info = "this is A";
void printA() {
print("A");
}
void run() {
print("A Run");
}
}
// 定义一个 mixins A
class B {
void printB() {
print("B");
}
void run() {
print("B Run");
}
}
// 定义一个类 C 继承自 Person , 然后混入类 B 和 A
class C extends Person with B, A {
C(String name, num age) : super(name, age);
}
void main() {
var c = new C('张三', 20);
c.printInfo(); // 张三----20
c.printB(); // B
print(c.info); // this is A
c.run(); // A Run
}
mixins 的类型就是其超类的子类型。
class A {
String info = "this is A";
void printA() {
print("A");
}
}
class B {
void printB() {
print("B");
}
}
class C with A, B {}
void main() {
var c = new C();
print(c is C); // true
print(c is A); // true
print(c is B); // true
var a=new A();
print(a is Object); // true (所有类均是 Object 的子类)
}
泛型就是解决 类 接口 方法的复用性、以及对不特定数据类型的支持(类型校验)
// 通过 T 指定泛型
// 传入number 类型必须返回number类型 传入 string类型必须返回string类型
getData<T>(T value) {
return value;
}
void main() {
print(getData(21)); // 21
print(getData('xxx')); // XXX
print(getData<String>('你好')); // 你好
print(getData<int>(12)); // 12
}
泛型类
class MyList<T> {
List list = <T>[];
void add(T value) {
this.list.add(value);
}
List getList() {
return list;
}
}
main() {
MyList l3 = new MyList<int>();
l3.add(11); // 报错
l3.add("aaaa");
print(l3.getList());
}
泛型接口
abstract class Cache<T> {
getByKey(String key);
void setByKey(String key, T value);
}
class FlieCache<T> implements Cache<T> {
@override
getByKey(String key) {
return null;
}
@override
void setByKey(String key, T value) {
print("我是文件缓存 把key=${key} value=${value}的数据写入到了文件中");
}
}
class MemoryCache<T> implements Cache<T> {
@override
getByKey(String key) {
return null;
}
@override
void setByKey(String key, T value) {
print("我是内存缓存 把key=${key} value=${value} -写入到了内存中");
}
}
void main() {
MemoryCache m = new MemoryCache<Map>();
m.setByKey('index', {"name": "张三", "age": 20});
}
在Dart中,库的使用是通过 import 关键字引入的。
library 指令可以创建一个库,每个Dart文件都是一个库,即使没有使用 library 指令来指定。
Dart中的库主要有三种:
1、我们自定义的库
import 'lib/xxx.dart';
2、系统内置库
import 'dart:math';
import 'dart:io';
import 'dart:convert';
3、Pub包管理系统中的库
https://pub.dev/packages
https://pub.flutter-io.cn/packages
https://pub.dartlang.org/flutter/
1、需要在自己想项目根目录新建一个pubspec.yaml
2、在pubspec.yaml文件 然后配置名称 、描述、依赖等信息
3、然后运行 pub get 获取包下载到本地
4、项目中引入库 import ‘package:http/http.dart’ as http; 看文档使用
// 系统内置库实现请求数据
import 'dart:io';
import 'dart:convert';
void main() async{
var result = await getDataFromZhihuAPI();
print(result);
}
//api接口: http://news-at.zhihu.com/api/3/stories/latest
getDataFromZhihuAPI() async{
//1、创建HttpClient对象
var httpClient = new HttpClient();
//2、创建Uri对象
var uri = new Uri.http('news-at.zhihu.com','/api/3/stories/latest');
//3、发起请求,等待请求
var request = await httpClient.getUrl(uri);
//4、关闭请求,等待响应
var response = await request.close();
//5、解码响应的内容
return await response.transform(utf8.decoder).join();
}
async和await
1、只有async方法才能使用await关键字调用方法
2、如果调用别的async方法必须使用await关键字
async是让方法变成异步。
await是等待异步方法执行完成。
void main() async{
var result = await testAsync();
print(result);
}
// 异步方法
testAsync() async{
return 'Hello async';
}
1、从下面网址找到要用的库
https://pub.dev/packages
https://pub.flutter-io.cn/packages
https://pub.dartlang.org/flutter/
2、创建一个pubspec.yaml文件,内容如下
name: "xxx"
description: "A new flutter module project".
dependencies:
http: ^0.12.0+2
date_format: ^1.0.6
3、配置dependencies
4、运行pub get 获取远程库
5、看文档引入库使用
当引入两个库中有相同名称标识符的时候,如果是java通常我们通过写上完整的包名路径来指定使用的具体标识符,甚至不用import都可以,但是Dart里面是必须import的。当冲突的时候,可以使用as关键字来指定库的前缀。如下例子所示:
import 'lib/Person1.dart';
import 'lib/Person2.dart' as lib;
main(List<String> args) {
Person p1=new Person('张三', 20);
p1.printInfo();
lib.Person p2=new lib.Person('李四', 20);
p2.printInfo();
}
如果只需要导入库的一部分,有两种模式:
模式一:只导入需要的部分,使用show关键字,如下例子所示:
import 'package:lib1/lib1.dart' show foo;
模式二:隐藏不需要的部分,使用hide关键字,如下例子所示:
import 'package:lib2/lib2.dart' hide foo;
也称为懒加载,可以在需要的时候再进行加载。
懒加载的最大好处是可以减少APP的启动时间。
懒加载使用deferred as关键字来指定,如下例子所示:
import 'package:deferred/hello.dart' deferred as hello;
当需要使用的时候,需要使用loadLibrary()方法来加载:
greet() async {
await hello.loadLibrary();
hello.printGreeting();
}