Dart基础知识

简介

  • Dart是由谷歌开发的计算机编程语言,它可以被用于web、服务器、移动应用 和物联网等领域的开发。
  • Dart诞生于2011年,号称要取代JavaScript。但是过去的几年中一直不温不火。直到Flutter的出现现在被人们重新重视。
  • 要学Flutter的话我们必须首先得会Dart
  • 官网:https://dart.cn/

基本

  • C语言一样,入口方法是main()方法
main() { print('hello'); } // 表示main方法没有返回值 // void main(){ // print('hello'); // }
  • 语句后面需要带;

重要的概念

在学习 Dart 语言时, 应该基于以下事实和概念:

  • 任何保存在变量中的都是一个对象, 并且所有的对象都是对应一个的实例。 无论是数字,函数和 null 都是对象。所有对象继承自 Object 类。

  • 尽管 Dart 是强类型的,但是 Dart 可以推断类型,所以类型注释是可选的。 如果要明确说明不需要任何类型, 需要使用特殊类型 dynamic

  • Dart 支持泛型,如 List <int> (整数列表)或 List <dynamic> (任何类型的对象列表)。

  • Dart 支持顶级函数(例如 main() ), 同样函数绑定在类或对象上(分别是 静态函数 和 实例函数 )。 以及支持函数内创建函数 ( 嵌套 或 局部函数 ) 。

  • 类似地, Dart 支持顶级 变量 , 同样变量绑定在类或对象上(静态变量和实例变量)。 实例变量有时称为字段或属性。

  • Java 不同,Dart 没有关键字 “public”“protected”“private” 。 如果标识符以下划线(_)开头,则它相对于库是私有的。

  • 标识符 以字母或下划线(_)开头,后跟任意字母和数字组合。

Dart 工具提示两种类型问题:警告_和_错误。 警告只是表明代码可能无法正常工作,但不会阻止程序的执行。 错误可能是编译时错误或者运行时错误。 编译时错误会阻止代码的执行; 运行时错误会导致代码在执行过程中引发异常。

变量

  • dart是可以不预先定义变量类型 ,自动会类型推导
  • dart中定义变量可以通过var关键字可以通过类型来申明变量
  • 如果要明确说明不需要任何类型, 需要使用特殊类型dynamic
var str = 'this is var'; String str = 'this is var'; int str = 123;

备注

  • var后就不要写类型,写了类型不要var。比如var int a = 5;会报错
  • 未初始化时,变量默认值是null

常量

  • 使用final或者const修饰符
  • const:值不变 一开始就得赋值
  • final:可以开始不赋值 只能赋一次
  • final不仅有const的编译时常量的特性,最重要的它是运行时常量,并且final是惰性初始化,即在运行时第一次使用前才初始化
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. 变量的名字是区分大小写的如: ageAge是不同的变量。在实际的运用中也建议,不要用一个单词大小写区分两个变量。
  5. 标识符(变量名称)一定要见名知意:变量名称建议用名词,方法名称建议用动词

数据类型

数值 - int、double

  • int比如是整型。整数值不大于64位,具体取决于平台
  • double既可以是整型,也可以是浮点型。64位(双精度)浮点数
  • 运算符+-*/%
int a = 123; double b = 23.5; b = 24; var c = a + b; print(c); // 字符串 和 数字 互转 // String -> int var one = int.parse('1'); assert(one == 1); // String -> double var onePointOne = double.parse('1.1'); assert(onePointOne == 1.1); // int -> String String oneAsString = 1.toString(); assert(oneAsString == '1'); // double -> String String piAsString = 3.14159.toStringAsFixed(2); assert(piAsString == '3.14');

操作方法的库:dart:math

字符串 - String

  • 使用单引号'或者双引号"都可以
  • 多行使用三个单引号'或者三个双引号"包裹起来
  • 字符串中变量使用${str}
var str1 = 'this is str1'; String str2 = 'this is str2'; // 连续三个单引号或者三个双引号实现多行字符串对象的创建 String str3 = ''' str3 str3 '''; // 通过 ${expression} 的方式内嵌表达式。 如果表达式是一个标识符,则 {} 可以省略 print("$str1 $str2"); // 使用 + 运算符来把多个字符串连接为一个 print(str1 + " " + str2); // 使用 r 前缀,可以创建 “原始 raw” 字符串 var s = r"In a raw string, even \n isn't special.";

布尔值 - bool

  • 值为true或者false
// 检查空字符串。 var fullName = ''; assert(fullName.isEmpty); // 检查 0 值。 var hitPoints = 0; assert(hitPoints <= 0); // 检查 null 值。 var unicorn; assert(unicorn == null); // 检查 NaN 。 var iMeantToDoThis = 0 / 0; assert(iMeantToDoThis.isNaN);

数组 - List

  • Dart中,数组是列表对象,所以大多数人只是称它们为列表
// 会自动类型推断成 List<string> var list1 = ['aaa', 'bbb', 'ccc']; print(list1.length); print(list1[1]) var list2 = new List(); list2.add('张三'); // 指定列表中的每项是String类型 var list3 = new List<String>(); list3.add('张三');

List常用的属性和方法

  • 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():遍历
// 循环打印出每个项 List myList = ['香蕉','苹果','西瓜']; // for循环 for(var i = 0; i < myList.length; i++) { print(myList[i]); } // for in for(var item in myList){ print(item); } // forEach myList.forEach((value){ print("$value"); }); // 每项*2 生成一个新List List myList = [1, 3, 4]; // for 循环 List newList = new List(); for(var i = 0; i < myList.length; i++) { newList.add(myList[i] * 2); } // map var newList = myList.map((value) { return value*2; }); // 按条件查找 List myList = [1, 3, 4, 5, 7, 8, 9]; // where var newList = myList.where((value){ return value > 5; }); print(newList.toList()); // any 只要集合里面有满足条件的就返回true var f = myList.any((value){ return value>5; }); // every 每一个都满足条件返回true 否则返回false var f = myList.every((value) { return value > 5; });

Set

  • Set最主要的功能就是去除数组重复内容
  • Set是没有顺序且不能重复的集合,所以不能通过索引去获取值
var s1 = new Set(); s1.add('香蕉'); s1.add('苹果'); s1.add('苹果'); print(s1); // {香蕉, 苹果} print(s1.toList()); // 去除List中重复项 List myList=['香蕉','苹果','西瓜','香蕉','苹果','香蕉','苹果']; var s2 = new Set(); s2.addAll(myList); print(s2); print(s2.toList()); // forEach var s = new Set(); s.addAll([1, 222, 333]); s.forEach((value) => print(value)); // map var elements = <String>{}; elements.add('fluorine'); elements.addAll(halogens); assert(elements.length == 5);

字典 - Map

  • 通常来说,Map是一个键值对相关的对象。键和值可以是任何类型的对象。每个键只出现一次,而一个值则可以出现多次
var person = { "name": "张三", "age": 20, "work": ["程序员", "外卖员"] }; print(person); print(person['name']) var p = new Map(); p["name"] = "李四";

Map常用的属性和方法

  • keys:获取所有的key
  • values:获取所有的value
  • isEmpty:是否为空
  • isNotEmpty:是否不为空
  • remove(key):删除指定key的数据
  • addAll({...}):合并映射 给映射内增加属性
  • containsValue():查看映射内的值,返回true/false
  • forEach():遍历
  • map():遍历
  • where():遍历
  • any():遍历
  • every():遍历
Map person = { "name": "张三", "age": 20, "sex": "男" }; print(person.keys.toList()); print(person.values.toList()); print(person.isEmpty); print(person.isNotEmpty); // forEach person.forEach((key,value) { print("$key---$value"); });

Runes

  • RunesUTF-32编码的字符串。它可以通过文字转换成符号表情或者代表特定的文字。
main() { var clapping = '\u{1f44f}'; print(clapping); print(clapping.codeUnits); print(clapping.runes.toList()); Runes input = new Runes('\u2665 \u{1f605} \u{1f60e} \u{1f47b} \u{1f596} \u{1f44d}'); print(new String.fromCharCodes(input)); }

类型判断

  • 使用is关键字来判断类型
var str = '1234'; if (str is String) { print('string类型'); } else if (str is int) { print('int类型'); } else { print('其他类型'); }

类型转换

  • Number类型转换成String类型使用toString()
  • String类型转成Number类型使用int.parse()double.parse()
// String str = '123'; // var myNum = int.parse(str); // String str = '123.1'; // var myNum = double.parse(str); // 防止程序报错,可以用 try catch String price = ''; try { var myNum = double.parse(price); print(myNum); } catch(err) { print(0); } var count = 12; var strCount = count.toString();
  • 其他类型转换成Boolean类型
// isEmpty: 判断字符串是否为空 var str = ''; print(str.isEmpty); // 数字非0 var myNum = 123; print(myNum==0); // 非空 var count; print(count==null); // isNaN var myNum2 = 0 / 0; print(myNum2.isNaN);

运算符

类型判定运算符

asis, 和 is! 运算符用于在运行时处理类型检查:

if (emp is Person) { // Type check emp.firstName = 'Bob'; } (emp as Person).firstName = 'Bob';

赋值运算符

使用 = 为变量赋值。 使用 ??= 运算符时,只有当被赋值的变量为 null 时才会赋值给它。

// 将值赋值给变量a a = value; // 如果b为空时,将变量赋值给b,否则,b的值保持不变。 // 以下相当于: b = b == null ? value : b b ??= value;

条件表达式

expr1 ?? expr2:如果 expr1 不是null, 返回 expr1 的值; 否则, 执行并返回 expr2 的值。

// 以下相当于: a == null ? b : a a ?? b // 如果赋值是根据布尔值, 考虑使用 ?: var visibility = isPublic ? 'public' : 'private'; // 如果赋值是基于判定是否为 null, 考虑使用 ?? String playerName(String name) => name ?? 'Guest';

级联运算符

级联运算符 (..) 可以实现对同一个对像进行一系列的操作。
除了调用函数, 还可以访问同一对象上的字段属性。
这通常可以节省创建临时变量的步骤, 同时编写出更流畅的代码。

querySelector('#confirm') // 获取对象。 ..text = 'Confirm' // 调用成员变量。 ..classes.add('important') ..onClick.listen((e) => window.alert('Confirmed!')); // 等价于 var button = querySelector('#confirm'); button.text = 'Confirm'; button.classes.add('important'); button.onClick.listen((e) => window.alert('Confirmed!'));

函数

  • 形参需要带类型
  • 可选参数使用[]
  • 默认参数=
  • 命名参数使用{}
  • javascript语法一样,有箭头函数、匿名函数和闭包
String printUserInfo(String username, int age) { // 行参 return "姓名:$username---年龄:$age"; } print(printUserInfo('张三', 20)); // 实参 // 可选参数 String printUserInfo(String username, [int age]){ //行参 if (age! = null) { return "姓名:$username---年龄:$age"; } return "姓名:$username---年龄保密"; } // 默认参数。如果没有提供默认值,则默认值为 null String printUserInfo(String username, [String sex='男', int age]){ //行参 if (age! = null) { return "姓名:$username---年龄:$age"; } return "姓名:$username---年龄保密"; } print(printUserInfo('张三')); print(printUserInfo('小李', '女')); print(printUserInfo('小李', '女', 30)); // 命名参数 // 调用函数时,可以使用指定命名参数 paramName: value String printUserInfo(String username, {int age, String sex = '男'}) { if(age != null) { return "姓名:$username---性别:$sex--年龄:$age"; } return "姓名:$username---性别:$sex--年龄保密"; } print(printUserInfo('张三', age:20, sex:'未知')); // 使用 @required 注释表示参数是 required 性质的命名参数 const Scrollbar({ Key key, @required Widget child }) // 普通函数 vs 箭头函数 List list = [4, 1, 2, 3, 4]; var newList = list.map((value) { if (value > 2) { return value * 2; } return value; }); print(newList.toList()); // 箭头函数 var newList = list.map((value) => value>2 ? value * 2 : value); print(newList.toList());
  • 测试函数是否相等
void foo() {} // 顶级函数 class A { static void bar() {} // 静态方法 void baz() {} // 示例方法 } void main() { var x; // 比较顶级函数。 x = foo; assert(foo == x); // 比较静态方法。 x = A.bar; assert(A.bar == x); // 比较实例方法。 var v = A(); // A的1号实例 var w = A(); // A的2号实例 var y = w; x = w.baz; // 两个闭包引用的同一实例(2号), // 所以它们相等。 assert(y.baz == x); // 两个闭包引用的非同一个实例, // 所以它们不相等。 assert(v.baz != w.baz); }

类 - Class

  • 类可以直接放在一个dart文件中,在另一个文件中通过import引入使用
import 'lib/Person.dart'; Person p1 = new Person.setInfo('李四', 30); p1.printInfo();
  • dart中没有publicprivateprotected这些访问修饰符。可以使用_把一个属性或者方法定义成私有

构造函数

  • 默认构造函数名称和类名相同
class Person{ String name; int age; // 默认构造函数 Person(String name, int age) { this.name = name; this.age = age; } // 默认构造函数的简写 // Person(this.name, this.age); void printInfo(){ print("${this.name}----${this.age}"); } } Person p1 = new Person('张三', 20);
  • 构造函数可以写多个
class Person{ String name; 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}"); } } // 默认实例化类的时候调用的是 默认构造函数 Person p1 = new Person('张三', 20); // 命名构造函数 Person p2 = new Person.now(); Person p3 = new Person.setInfo('李四',30);
  • 工厂构造函数:当执行构造函数并不总是创建这个类的一个新实例时,则使用 factory 关键字
class Logger { final String name; bool mute = false; // 从命名的 _ 可以知, // _cache 是私有属性。 static final Map<String, Logger> _cache = <String, Logger>{}; factory Logger(String name) { if (_cache.containsKey(name)) { return _cache[name]; } else { final logger = Logger._internal(name); _cache[name] = logger; return logger; } } Logger._internal(this.name); void log(String msg) { if (!mute) print(msg); } }

getter && setter

  • 使用getset关键字定义
  • 调用的时候直接通过访问属性的方式访问
class Rect{ num height; num width; Rect(this.height, this.width); get area { return this.height * this.width; } set areaHeight(value) { this.height = value; } } Rect r = new Rect(10, 4); // 调用直接通过访问属性的方式访问area print("面积:${r.area}"); r.areaHeight = 6; print(r.area);

静态成员

  • 使用static关键字来实现类级别的变量和函数
  • 静态方法不能访问非静态成员,非静态方法可以访问静态成员
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(); // 静态方法没法访问非静态的属性 // print(this.age); // 静态方法没法调用非静态的方法 // this.printInfo(); } } print(Person.name); Person.show(); Person p = new Person(); p.printInfo(); Person.printUserInfo();

对象操作符

  • ?:条件运算符
  • as:类型转换
  • is:类型判断
  • ..:级联操作
class Person { String name; num age; Person(this.name, this.age); void printInfo() { print("${this.name}---${this.age}"); } } // ? Person p; p?.printInfo(); Person p = new Person('张三', 20); p?.printInfo(); // foo?.bar 非空调用 相当于: foo == null ? null : foo.bar // 从表达式foo中选择属性bar, // 除非foo为空(在这种情况下,foo?.bar值为空) // is Person p = new Person('张三', 20); if(p is Person){ p.name = "李四"; } p.printInfo(); print(p is Object); // as var p1; p1 = ''; p1 = new Person('张三1', 20); // p1.printInfo(); (p1 as Person).printInfo(); // .. Person p1 = new Person('张三1', 20); p1.printInfo(); p1..name = "李四" ..age = 30 ..printInfo();

类的继承

  • 子类使用extends关键词来继承父类
  • 子类会继承父类里面可见的属性和方法 但是不会继承构造函数
  • 子类能复写父类的方法gettersetter
  • 使用super给父类构造函数传参
  • 使用@override覆盖父类的方法
  • 在子类里面使用super调用父类的方法
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{ String sex; // 子类跟父类一样的参数(没有sex),可以去掉后面的{} // Web(String name, num age) : super(name, age); Web(String name, num age, String sex) : super(name, age){ this.sex = sex; } run(){ print('run'); // 调用父类的方法 super.work(); } // 覆写父类的方法。可以写也可以不写 建议在覆写父类方法的时候加上 @override @override void printInfo(){ print("姓名:${this.name}---年龄:${this.age}"); } }

抽象类

  • Dart抽象类主要用于定义标准,子类可以继承抽象类,也可以实现抽象类接口

  • 抽象类通过abstract关键字来定义

  • Dart中的抽象方法不能用abstract声明,Dart中没有方法体的方法我们称为抽象方法。

  • 如果子类继承抽象类必须得实现里面的抽象方法

  • 如果把抽象类当做接口实现的话必须得实现抽象类里面定义的所有属性和方法。

  • 抽象类不能被实例化,只有继承它的子类可以

extends抽象类和implements的区别:

  • 如果要复用抽象类里面的方法,并且要用抽象方法约束自类的话我们就用extends继承抽象类
  • 如果只是把抽象类当做标准的话我们就用implements实现抽象类
// 定义一个Animal 类要求它的子类必须包含eat方法 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('小猫在跑'); } } // 下面这种写法是错误的,抽象类没法直接被实例化 // Animal a=new Animal();

多态

  • 允许将子类类型的指针赋值给父类类型的指针, 同一个函数调用会有不同的执行效果

  • 子类的实例赋值给父类的引用

  • 多态就是父类定义一个方法不去实现,让继承他的子类去实现,每个子类有不同的表现

abstract class Animal{ eat(); // 抽象方法 } class Dog extends Animal{ @override eat() { print('小狗在吃骨头'); } run(){ print('run'); } } class Cat extends Animal{ @override eat() { print('小猫在吃老鼠'); } run(){ print('run'); } }

接口

  • dart的接口没有interface关键字定义接口,而是普通类或抽象类都可以作为接口被实现

  • 使用implements关键字进行实现

  • 如果实现的类是普通类,会将普通类和抽象中的属性的方法全部需要覆写一遍

  • 而因为抽象类可以定义抽象方法,普通类不可以,所以一般如果要实现像Java接口那样的方式,一般会使用抽象类

  • 建议使用抽象类定义接口

接口实现

// 定义一个DB库 支持 mysql mssql mongodb // mysql mssql mongodb三个类里面都有同样的方法 abstract class Db{ // 当做接口 接口:就是约定 、规范 String uri; // 数据库的链接地址 add(String data); save(); delete(); } class Mysql implements Db{ @override String uri; Mysql(this.uri); @override add(data) { // TODO: implement add print('这是mysql的add方法'+data); } @override delete() { // TODO: implement delete return null; } @override save() { // TODO: implement save return null; } remove(){ } } class MsSql implements Db{ @override String uri; @override add(String data) { print('这是mssql的add方法'+data); } @override delete() { // TODO: implement delete return null; } @override save() { // TODO: implement save return null; } } class MongoDb implements Db{ @override String uri; @override add(String data) { print('这是MongoDb的add方法'+data); } @override delete() { // TODO: implement delete return null; } @override save() { // TODO: implement save return null; } }

代码分离

可以将代码分离到不同的文件中,实现代码分离。

  • 新建Db.dart文件
abstract class Db{ // 当做接口 接口:就是约定 、规范 String uri; // 数据库的链接地址 add(String data); save(); delete(); }
  • 新建MySql.dart文件
import 'Db.dart'; class Mysql implements Db{ @override String uri; Mysql(this.uri); @override add(data) { print('这是mysql的add方法'+data); } @override delete() { return null; } @override save() { return null; } }
  • 新建MsSql.dartMongDb.dart文件

多个接口

abstract class A{ String name; printA(); } abstract class B{ printB(); } class C implements A,B{ @override String name; @override printA() { print('printA'); } @override printB() { // TODO: implement printB return null; } }

mixins

  • mixins的中文意思是混入,就是在类中混入其他功能。

  • Dart中可以使用mixins实现类似多继承的功能

  • 使用with关键字实现

  • 作为mixins的类只能继承自Object,不能继承其他类
  • 作为mixins的类不能有构造函数
  • 一个类可以mixins多个mixins
  • mixins绝不是继承,也不是接口,而是一种全新的特性
// 简单混入 class A { String info = "this is A"; void printA(){ print("A"); } } class B { void printB() { print("B"); } } class C with A, B{ }
// 继承+混入 class Person{ String name; num age; Person(this.name, this.age); printInfo() { print('${this.name}----${this.age}'); } void run() { print("Person Run"); } } class A { String info = "this is A"; void printA() { print("A"); } void run() { print("A Run"); } } class B { void printB() { print("B"); } void run() { print("B Run"); } } class C extends Person with B,A{ C(String name, num age) : super(name, age); }

泛型

  • 通俗理解:泛型就是解决类、接口、方法的复用性、以及对不特定数据类型的支持(类型校验)
//只能返回string类型的数据 String getData(String value) { return value; } // 同时支持返回string类型和int类型(代码冗余) String getData1(String value) { return value; } int getData2(int value) { return value; } // 同时返回string类型和number类型 - 不指定类型可以解决这个问题 getData(value) { return value; } // 不指定类型放弃了类型检查 // 我们现在想实现的是传入什么 返回什么 // 比如:传入number 类型必须返回number类型 传入 string类型必须返回string类型 // T getData<T>(T value) { // return value; // } getData<T>(T value) { return value; } print(getData(21)); print(getData('xxx')); getData<String>('你好'); print(getData<int>(12));
// 集合List泛型类的用法 // 把下面类转换成泛型类,要求List里面可以增加int类型的数据,也可以增加String类型的数据。但是每次调用增加的类型要统一 List list = new List<String>(); // list.add(12); // 错误的写法 list.add('你好'); class PrintClass<T> { List list = new List<T>(); void add(T value){ this.list.add(value); } void printInfo() { for(var i = 0; i < this.list.length; i++) { print(this.list[i]); } } } PrintClass p1 = new PrintClass<String>(); p1.add('你好'); p1.add('哈哈'); p1.printInfo(); PrintClass p2 = new PrintClass<int>(); p2.add(12); p2.add(23); p2.printInfo();
// Dart中的泛型接口: // 实现数据缓存的功能:有文件缓存、和内存缓存。内存缓存和文件缓存按照接口约束实现。 // 1、定义一个泛型接口 约束实现它的子类必须有getByKey(key) 和 setByKey(key,value) // 2、要求setByKey的时候的value的类型和实例化子类的时候指定的类型一致 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} -写入到了内存中"); } } MemoryCache m1 = new MemoryCache<String>(); m1.setByKey('index', '首页数据'); MemoryCache m2 = new MemoryCache<Map>(); m2.setByKey('index', {"name":"张三","age":20});

  • 实际开发中,模块化很重要,所以这就需要使用到库的概念

  • Dart中,库的使用时通过import关键字引入的

  • library指令可以创建一个库,每个Dart文件都是一个库,即使没有使用library指令来指定。

  • 当引入两个库中有相同名称标识符的时候,可以使用as关键字来指定库的前缀

import 'lib/Person1.dart'; import 'lib/Person2.dart' as lib;
  • 部分导入:可以使用show关键字只导入需要的部分;或者使用hide关键字隐藏不需要的部分
import 'package:lib1/lib1.dart' show foo; import 'package:lib2/lib2.dart' hide foo;
  • 延迟加载使用deferred as关键字来指定。当需要使用的时候,需要使用loadLibrary()方法来加载
import 'package:deferred/hello.dart' deferred as hello; greet() async { await hello.loadLibrary(); hello.printGreeting(); }

自定义的库

  • 导入方式:import 'lib/xxx.dart';

系统内置库

  • 导入方式如下
import 'dart:math'; import 'dart:io'; import 'dart:convert';
// 导入系统内置库实现请求数据httpClient 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(); }

Pub包管理系统中的库

  • 从下面网址找到要用的库
  • 创建一个pubspec.yaml文件,内容如下
name: xxx description: A new flutter module project. dependencies: http: ^0.12.0+2 date_format: ^1.0.6
  • 配置pubspec.yaml文件中的dependencies

  • 运行pub get获取远程库

  • 看文档引入库使用

import 'dart:convert' as convert; import 'package:http/http.dart' as http; import 'package:date_format/date_format.dart'; print(formatDate(DateTime(1989, 2, 21), [yyyy, '*', mm, '*', dd]));

创作不易,若本文对你有帮助,欢迎打赏支持作者!

 分享给好友: