拉钩

基础

image

基础环境:

操作系统 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/open in new window

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

image

JDK

下载地址:https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html

安装 android stuio

image

image

flutter doctor 检测环境是否满足

版本切换解决问题

image

查看模拟器

flutter emulators

启动模拟器

flutter emulators --launch Pixel_3a_XL_API_33

https://blog.csdn.net/qq_40166103/article/details/125673747open in new window

dart 与 javascript 差异

DartJavaScript
FlutterReact
https://pub.devhttps://npmjs.comopen in new window
pubnpm

dart 官网介绍:https://dart.cn/get-dartopen in new window

环境变量

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 = 182.不明确类型:var age=18;dynamic age = 18;
变量名大小写敏感(age 与 Age是两个不同的变量)
变量默认值是null(js中变量默认值是undefined)
Dart变量的值是不会进行隐式转换(null不会自动转换成false

基础语法-常量

常量是值不可该表的变量(一旦声明 其值不能更改)
声明常量
const age = 18;(编译时)
final age = 18;(运行时+编译时)
constfinal 的区别
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
}



image

类和对象

类 继承 抽象类 接口 混入 泛型  枚举

类:构造器(构造函数) 访问修饰 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);
}





image

元数据

元数据

  • 元数据以@开头,可以给代码标记一些额外的信息
    
  • 元数据可以用来库,类,构造器,函数,字段,参数或变量声明的前面
    
  • @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{...}
  • 混入(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)

image

自定义库

自定义库-通过 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 来组装库

image

系统库

  • 系统库(也叫核心库)是 Dart 提供的常用内置库
    • 不需要单独下载,就可以直接使用
  • 引入
    • import 'dart:库名';
    • import 'dart:core';//会自动引入(无需手动引入)
  • 系统库列表

第三方库

来源

使用

  • 在项目目录下创建 pubspec.yaml
  • 在 pubspec.yaml 中声明第三方库(依赖)
  • 命令行中进入 pubspec.yaml 所在目录,执行 pub get 进行安装
  • 项目中引入已安装的第三方库(import 'package:xxxx/xxx.dart';)

第三方库接口

image

pubspec.yaml

官网:

https://flutter.dev

github

https://github.com/flutter/flutter

中文网

https://flutterchina.club/

https://flutter.cn/

git:

flutter 开发需要 git 支持

下载: https://git-scm.com/downloadopen in new window

git --version

image

image

image

Last Updated:
Contributors: 刘荣杰