Dart 强大的脚本语言,Dart是一门使用类和单继承的面向对象的语言,所有的对象都是类的实例,并且所有的类都是object的子类。Dart 中的抽象类主要用来定义标准,子类可以继承抽象类,也可以实现抽象类接口。把接口定义成抽象类。
一个类是属性和方法组
1.Dart 配置,运行Hellow word
mac 安装,直接命令行
https://dart.dev/get-dart
windows
下载dart sdk 软件包
https://gekorm.com/dart-windows/
安装过程 比较慢
dart --version
开发工具:IDEA
![在这里插入图片描述](https://img-blog.csdnimg.cn
void main(){
print("hellow word"); hellow word
}
2.入口方法 打印 注释 变量 常量命名 规则
无返回值的方法
void main() {
print("hellow word");
}
定义变量
- 方法1 var 自动推断类型
var str='hellow word';
print(str);
- 方法2
String str= 'hellow word';
print(str);
final 和const
const 值不变 一开始就得赋值
final 可以开始不赋值,只能赋一次,运行时的常量 ,final是惰性初始化,即在运行第一次才使用
3.数据类型详解 int double String bool List Maps
1.三个引号,双引号和单引号都可以
var str = "hellow";
var str1 = 'hellow';
var str3 = '''
hellow
word
''';
var str4 = """
hellow
word
""";
print(str3);
字符串拼接 + 和 $
print("$str $str1");
2.double 既可以是整型也可以是浮点型
3.list
//1
var list=["aaa","bbbb",20,true];
//2指定对应类型
var list=<String>["aaa","bbbb"];
//3[]创建的,容量可变
var list=[];
print(list);
list.add(20);
print(list);
//4.最新版本 去掉了 new List()
//创建固定长度的集合
var list = List.filled(5, "");
print(list); [, , , , ]
list[1] = "40";
print(list);[, 40, , , ]
//指定类型
var list = List<String>.filled(5, "");
3.Maps
//1定义maps
var person = {
"name":"张三",
"age":20,
"work":["程序员","外卖员"]
};
print(person); {name: 张三, age: 20, work: [程序员, 外卖员]}
//2定义maps
var p=new Map();
p["name"]="张三";
p["age"]=20;
p["work"]=["程序员","外卖员"];
print(p);
print(p["age"]);
is 判断类型
var str = "1234";
if (str is int) {
print(false);
}
}
4.运算符 条件判断 类型转化
1.a = a + 10; 同 a+=10;
2.三目运算符
var flag = true;
String str = flag ? "我是ture" : "我是false";
print(str);
2.??
var a;
var b= a?? 10;
print(b); 10
3.类型转换
String 转 double
String prince="12.1";
var num=double.parse(prince);
print(num); 12.1
String prince="";
try{
var num=double.parse(prince);
print(num);
}catch(err){
print(err);
}
isEmpty 判断是否为空
String prince="";
print(prince.isEmpty); true
print(prince==null); false
String prince;
print(prince==null); true
5.循环语句 for while do…while break continue 多维列表循环
1. 自增写在前后的区别(赋值)
在赋值运算里,如果++ – 卸载前面 ,这时候 ,先运算 再赋值 ;如果 ++ --卸载后面,先赋值 再运算
var a = 10;
var b = a++;
var c = ++a;
print(a); 12
print(b); 10
print(c); 12
a++ 和 ++a 单独写没区别,都是自增1
2.for循环
//数组里面有对象
List list = [
{"title": "新闻111"},
{"title": "新闻222"}
];
list.forEach((element) {
print(element['title']);
});
//二维数组
List list1 = [
{
"cate": '国内',
"news": [
{"title": "国内新闻111"},
{"title": "国内新闻222"}
]
},
{
"cate": '国际',
"news": [
{"title": "国际新闻333"},
{"title": "国际新闻444"}
]
}
];
for (var i = 0; i < list1.length; i++) {
print(list1[i]["cate"]);
var news = list1[i]["news"];
for (var j = 0; j < news.length; j++) {
print(" "+news[j]["title"]);
}
}
输出结果
新闻111
新闻222
国内
国内新闻111
国内新闻222
国际
国际新闻333
国际新闻444
3.while (防止死循环需要加i++) do…while
唯一区别:第一次循环不满足条件的时候
int i=1;
int sum=0;
while(i<=10){
sum+=i;
print(sum);
i++;
}
int i=1;
int sum=0;
do{
sum+=i;
i++;
}while(i<=10);
print(sum);
4.break 跳出一层当前循环 ,continue 跳过当前循环 继续循环;
用在switch case;for while 中
6.List Set Map 详解 forEach map where any every
1.List常用属性和方法:
- length 长度
- reversed 反转
- isEmpty 是否为空
- isNotEmpty 是否不为空
- add 增加
- addAll 拼接数组
- indexOf 查找 传入具体值
- remove 删除 传入具体值
- removeAt 删除 传入索引值
- fillRange 修改
- insert(index,value)
- toList
- join list转成字符串
- split 字符串转成list
- forEach
- map
- where
- any
- every
2.Set 去重
var s=new Set();
s.add("apple");
List list=["aa","bb","aa"];
print(list.toSet()); ["aa","aa"]
3.Map 映射无序键值对 常用属性和方法
- keys 获取所有key值
- values 获取所有value 值
- isEmpty
- isNotEmpty
- remove(key)
- addAll({…})
- containsValues 查找映射内的值 返回true false
- forEach
- map
- where
- any
- every
var m = new Map();
m.addAll({"name": "张三"},);
m.addAll({"age": "10"});
print(m.values.toList());
print(m.containsValue("10"));
m.forEach((key,value) {
print("$key $value");
});
3.Map
var ll=["aa","bb","cc"];
var nn=ll.map((e) => "jia$e");
print(ll);
print(nn.toList());
[aa, bb, cc]
[jiaaa, jiabb, jiacc]
4.Where
var ll=["aa","bb","cc"];
var nn=ll.where((element) => element=="aa");
print(ll);
print(nn.toList());
[aa, bb, cc]
[aa]
5.Any 只要集合中有一个满足条件 返回true
var ll = ["aa", "bb", "cc"];
var nn = ll.any((element) => element == "aa");
print(ll);
print(nn);
var f=ll.any((element){
return element == "aa";
});
print(f);
[aa, bb, cc]
true
true
6.Every 集合中每一个满足条件 才返回true
7.函数的定义 可选参数 默认参数 箭头函数 匿名函数 闭包
返回类型可以不写,但是建议写
1.自定义方式放在main 以外,和顺序无关,全局作用域;如果放在main方法里面,和顺序有关,局部作用域;
print(getSum(100));
//定义一个所有数的和
int getSum(int n) {
var sum=0;
for (var i = 1; i <= n; i++) {
sum += i;
}
return sum;
}
2.可选参数 中括号[int? age,String? sex]
String getUserInfo(String name, [int? age]) {
if (age != null) {
return "$name $age";
}else{
return "$name 年龄保密";
}
}
print(getUserInfo("张三")); 张三 年龄保密
3.默认参数 [int? age=18]
String getUserInfo(String name, [int? age=18]) {
if (age != null) {
return "$name $age";
}else{
return "$name 年龄保密";
}
}
4.命名参数 花括号 {int? age=18}
print(getUserInfo("张三",age: 20));
5.把方法当作参数
6.箭头函数 => 里面无分号 ,里面只能写一行
List list = ["aa", "bb", "cc"];
list.forEach((element) {
print(element);
});
list.forEach((element) => {
//只能写一句话
print(element)
});
List list = [1, 2, 3];
var newList1 = list.map((value) => value > 2 ? value * 2 : value);
print(newList1.toList()); [1, 2, 6]
7.匿名函数 (没有名字的方法)
var printNum=(){
print(123);
};
printNum();
var printNum=(int n){
print(123+n);
};
printNum(1);
8.自执行方法 ((){})();
((int n){
print("我是自执行方法$n");
})(13);
我是自执行方法13
9.方法的递归
var sum = 1;
fn(int n) {
sum *= n;
if (n == 1) {
return;
}
fn(n - 1);
};
fn(5);
print(sum);120
var sum = 0;
fn(int n) {
sum += n;
if (n == 0) {
return;
}
fn(n - 1);
}
fn(10);
print(sum);
55
10.全局变量和局部变量和闭包
全局变量常驻内存,污染全局;局部变量,不会常驻内存,会被垃圾回收机制回收,不污染全局;闭包,常驻内存,不污染全局;
闭包写法:函数嵌套函数,并return里面的函数,这样形成闭包。
fn() {
var a = 123;
return () {
a++;
print(a);
};
}
var b=fn();
b();
b();
b();
124
125
126
8.对象 类 类的创建 构造函数 命名构造函数 类模块化 私有属性 私有方法 get set
面向对象:封装 继承 多态,Dart虽有的东西都是对象,所有的对象都继承自Object
dart是一门使用类和单继承的面向对象的语言,所有的对象都是类的实例,并且所有的类都是object的子类
一个类是属性和方法组成的
类模块化:单独一个类
使用_下划线把一个属性或方法定义成私有,必须是单独的一个文件,间接的调用私有属性或方法;
1.单独类
import 'libs/Person.dart';
void main() {
var p1 = new Person("张三", 25);
//Person p1 = new Person();
p1.age = 20;
p1.getInfo();
//调用命名构造函数
var p2 = new Person.now();
//_sex为私有
p2.getSex();
}
class Person {
String name = "张三";
//私有,其它类直接访问不到
String _sex = "男";
String getSex() {
return _sex;
}
int age = 10;
// Person(){
// print("我是构造函数 实例化的时候触发");
// }
//默认构造函数
// Person(String name,int age){
// this.name=name;
// this.age=age;
// }
//默认构造函数的简写
Person(this.name, this.age);
Person.now() {
print("我是命名构造函数");
}
void setInfo(int age) {
this.age = age;
}
void getInfo() {
// print("$name$age");
print("${this.name}----${this.age}");
}
}
2.get set方法
class Rect {
num height;
num width;
//初始化之前的动态赋值
//Rect():height=1,width=2
Rect(this.height, this.width);
get area {
return this.height * this.width;
}
set areaHeight(value){
this.height=value;
}
}
Rect rect = new Rect(10, 4);
rect.areaHeight=6;
print("面积:${rect.area}");
9.类 静态成员 操作符 类的继承
1.静态, 直接调用
静态方法不能访问非静态成员,非静态方法可以访问静态成员
2.Dart中的对象操作符 … 级联操作
- … 级联操作 (记住)
void main() {
Person p = new Person();
p..name = "xx"
..age = 30
..show();
}
class Person {
String name = "张三";
int age = 10;
void show() {
print(name);
print(this.age);
}
}
- ? 条件运算符 (不用)
- as 类型转换
- is 类型判断
3.继承 extends super this
void main() {
Person p = new Person("lx",20);
p.show();
Web web=new Web("zs", 10,"女");
web.show();
}
class Person {
String name;
int age;
Person(this.name, this.age);
Person.xxx(this.name, this.age);
void show() {
print(name);
print(this.age);
}
}
class Web extends Person {
String sex="男";
// Web(super.name, super.age);
// Web(String name, int age):super(name,age);
Web(String name, int age,String sex):super(name,age){
this.sex=sex;
}
// Web(String name, int age,String sex):super.xxx(name,age){
// this.sex=sex;
// }
@override
show(){
print(sex);
}
work(){
super.show();
}
}
10.抽象类 abstract、 多态 接口
Dart 中的抽象类:主要用来定义标准,子类可以继承抽象类,也可以实现抽象类接口。把接口定义成抽抽象类。抽象类不能被实例化
要求所有子类都要有某个方法
多态 父类定义方法不去实现,让子类去实现方法,每个子类有不同的表现。
Dart 接口没有interface关键字,而是普通类和抽象类都可以定义接口
void main() {
Dog dog=new Dog();
dog.eat();
dog.run();
dog.printInfo();
}
abstract class Animal{
String name="";
eat();
run();
printInfo(){
print("我是一个抽象类普通方法");
}
}
class Pig implements Animal{
@override
eat() {
// TODO: implement eat
throw UnimplementedError();
}
@override
printInfo() {
// TODO: implement printInfo
throw UnimplementedError();
}
@override
run() {
// TODO: implement run
throw UnimplementedError();
}
@override
String name="pig";
}
class Dog extends Animal{
@override
eat() {
print("小狗吃骨头");
}
@override
run() {
print("小狗在跑");
}
}
class Cat extends Animal{
@override
eat() {
print("小猫吃鱼");
}
@override
run() {
print("小猫在跑");
}
}
11.一个类实现多个接口 ,Mixins
1.class C implements A,B
void main() {
C c=new C();
c.printA();
}
abstract class A {
String name="";
printA();
}
abstract class B {
printB();
}
class C implements A,B {
@override
String name="";
@override
printA() {
print("A");
}
@override
printB() {
print("B");
}
}
2.Mixins 类似多继承的功能
Mixins超类的子类
使用要求
- 作为mixins的类只能继承自object,不能继承其它类
- 作为mixins的类不能有构造函数
- 一个类可以mixins多个mixins类
- mixins绝不是继承,也不是接口,而是一种全新的特性
void main() {
C c = new C("张三",2);
c.printA();
c.printB();
c.a;
}
class Person {
String name = "";
int age = 0;
Person(this.name, this.age);
printInfo() {
print("我是一个person类");
}
}
class A {
String a = "saaaa";
printA() {
print("A");
}
}
class B {
printB() {
print("B");
}
}
class C extends Person with A, B {
C(String name, int age) : super(name, age);
}
12.泛型 泛型方法 泛型类 泛型接口
泛型就是解决 类 接口 方法的复用性 以及对不特定数据类型的支持(类型校验),解决代码重用问题。
1.泛型方法
void main() {
print(getData4(21));
print(getData4("xxx"));
getData4<String>("hellow");
getData4<int>(123);
}
//同事支持返回String, int 类型
//代码冗余
String getData1(String value) {
return value;
}
int getData2(int value) {
return value;
}
//放弃了类型的检查
getData3(value) {
return value;
}
//泛型函数 :代码复用 类型校验
T getData4<T>(T value) {
return value;
}
2.泛型类 MyList < T >
//创建集合(两种方式)
List ll = [];
List ll2 = new List.filled(2, ""); //长度为2的集合
List ll3 = List<String>.filled(2, ""); //长度为2的集合,指定类型,用到了泛型类
List list = List.filled(2, ""); //长度为2的集合
list[0] = "aa";
list[1] = "bb";
print(list);
void main() {
// 指定类型,只能添加String类型
//MyList<String> list= MyList();
// MyList list= MyList<int>();
//不指定类型,可以添加任意类型
MyList list = MyList();
list.add(1);
list.add(2);
print(list.getList());
list.add("aa");
list.add("bb");
print(list.getList());
}
class MyList<T> {
List list = <T>[];
void add(T value) {
this.list.add(value);
}
List getList() {
return list;
}
}
3.泛型接口 (抽象类)
void main() {
//实现数据缓冲的功能,有文件缓冲和内存缓冲 内存缓冲和文件缓冲按照接口来实现
MemoryCache m = new MemoryCache<String>();
m.setByKey("index", "aa");
MemoryCache m1 = new MemoryCache<Map>();
m1.setByKey("index", {"name":"zs","age":11});
}
abstract class Cache<T> {
getByKey();
void setByKey(String key, T value);
}
class FileCache<T> implements Cache<T> {
@override
getByKey() {
return null;
}
@override
void setByKey(String key, T value) {
print("我是文件缓冲$key$value");
}
}
class MemoryCache<T> implements Cache<T> {
@override
getByKey() {
return null;
}
@override
void setByKey(String key, T value) {
print("我是内存缓冲$key$value");
}
}
13.库 自定义库 系统内置库 第三方库
1.自定义库
单独的类
import ‘libs/Person.dart’;
2.系统内置库 dart:
import ‘dart:math’;
import ‘dart:io’;
async 和 await
- 只有async方法才能使用await 关键字调用方法
- 如果调用别的async方法必须使用await关键字
import 'dart:io';
void main() async {
var result = await testAsync();
print(result);
}
//异步方法
testAsync() async{
return "Hello async";
}
3.第三方模块
pub包管理系统
- 1从下面网址找到要用的库
https://pub.dev/packages
https://pub.flutter-io.cn/packages
https://pub.dartlang.org/flutter/ - 2创建一个pubspec.yaml文件
name: xxx
environment:
sdk: '>=2.10.0 < 3.0.0'
dependencies:
http: ^0.13.5
date_format: ^2.0.7
- 3配置dependencies
- 4执行pub get获取远程库
- 5看文档因入库使用
4.库、模块的冲突和重命名
import 'libs/Person.dart' as personOne;
import 'dart:convert' as convert;
import 'package:http/http.dart' as http;
如果只需要导入库的一部分,有两种模式
- 模式1:汁倒入需要的部分,使用show 关键字,如下
import 'libs/Person.dart' show getInfo;
- 模式2:隐藏不需要的功能 hide
import 'libs/Person.dart' hide getInfo;
14.2.13后新特性 Null safety late 空类型声明符? 非空断言! require
最新版本不能
Null safety 空安全 改善性能 ?可空类型 !类型断言
late 延迟初始化
15.性能优化之 常量、identical函数 常量构造函数
const 声明的常量是爱编译时确定的,永远不改变
final 声明的常量允许声明后再赋值,赋值后不可改变,final声明的变量实在运行时确定的
final不仅有const的编译时常量的特性,最重要的是运行时常量
const PI = 11;