手把手教你使用dart-后续继续更新

86 阅读7分钟

dart是以.dart为结尾的文件

dart入口方法介绍 mian

1main(){}

2void main(){}

所有的方法都是放到main方法里面

区别:void main代表没有返回值

类似js
function main():void {}

声明变量-可以通过var、类型(String int)来声明

var声明变量(自动推断类型) dynamic可以更改类型

void main(List<String> args) {
  var name = "zhangsan"; // 定义一个变量,用来表示姓名
  var age = 18;
  var height = 1.78;

  name = "李四"; // 修改变量的值
  // name = 123; // 错误, name是字符串类型的,无法赋值其他类型数据
  age = 19;

  print(name);
  print(age);
  print(height);
  
  var定义变量以后 是无法更改类型的 但是dynamic可以
   dynamic variable = "Hello World";
    variable = 456;
    print(variable);
}

类型声明变量

字符串(String)
String str = '123'
int str = 456 
数值类型(int double-浮点)
int str = 123
int str1 = 123.1 报错
double str2 = 456.5 
double str3 = 456 可以输出 456.0

int只能是整型 double可以是整型也可以是小数点(浮点)
布尔值类型(bool)
bool str = true 输出为true

注意

dart会自动推断类型 比如var a = 123 当重新赋值不同类型会报错

数组和对象(List 和 Map)

数组

未定义变量类型以及创建数组
void main(){
  var array = [123,'456'];
  print(array);
}
输出 [123, 456]
定义变量类型
void main(){
  var array = <String>['456','456'];
  print(array);
}
输出 ['456', '456']
创建指定长度的数组(不可更改和添加-List.filled(length,fill))
void main(){
  var a = List.filled(2, '1');
}
创建自带去重的数组
var map10 = new Set();
map10.add('苹果');
map10.add('苹果');
print(map10.toList());
输出[苹果]
定义变量类型
void main(){
  var a = List<String>.filled(2, '1');
}
添加数组的值(add)
void main(){
  var array = [123,'456'];
  array.add('222');
  print(array);
}
输出[123, '456', '222']
获取数组的值(下标获取)
void main(){
  var array = [123,'456'];
  array.add('222');
  print(array[0]);
}
输出123
数组其他操作

void main () {
  print("---_listType---");
  List list1 = [2,2,3,4,5,6];
  List<int> list2 = [];
  list2.add(1);
  list2.add(2);
  List list3 = [1,2,3,'集合'];
  var list4 = [{    'name':123  }];
  list2.add(2);//添加一条数据
  list2.addAll([2,3,4]);//添加多个数据-拼接数组
  list1.reversed; //翻转
  list1.removeAt(0); // 移除集合中指定位置的值,打印移除的值
  list1.remove(2); // 移除指定的字符串
  list1.removeRange(0, 1); // 移除开始位置,到结束位置的值
  list1.insert(0, 1); // 指定位置,插入数据
   list1.insertAll(0, ['2','333']); // 指定位置,插入多哥数据 
  list1.fillRange(1, 3, 0); //修改指定位置的值
  list1.sublist(0, 2); // 截取开始到结束位置的值
  list1.indexOf(8); // 是否包含指定的数据,如果包含,返回值得位置;反之,返回-1;
 list1.any((v)=>v > 1); // 判断是否有满足条件的 有就返回true 没有false
  list1.every((v)=>v > 0); // 判断所有数据是否满足条件 有就返回true 没有false
  list1.join(','); // 将数组用指定字符拼接成字符串
  list1.toSet().toList(); //数组去重
  //数组去重
  var list3 = new Set()
  list3.addAll(list1)
  
  list1.where((person) => person > 22).toList() //过滤符合条件的数据 类似js的filter
  map5.map((item)=>item['name']).toList() //返回一个新的数组 类似js的map
  // 集合循环的方式
  for(int i=0; i<list3.length; i++){
    print(list3[i]);
  }

  for(var o in list3){
    print(o);
  }

  list3.forEach((element) {
    print(element);
  });

  print(list1.every((v)=>v > 0)); // 判断是否有满足条件的 有就返回true 没有false

  var list = [1, 2, 2, 3, 4, 5, 6, 6];  // 将list所有元素加1并返回数组
  var v = list.map((e) {
    return e + 1;
  }).toList();
  print(v); //[2, 3, 3, 4, 5, 6, 7, 7]
  
var map5 = [  { "name": '张三', "age": 18 }];

var map6 = map5.map((item)=>item['name']).toList();

print(map6); [张三]
}

对象(Map 集合 类似js 但是获取值只能['变量'])

void main () {
  print("---MapType---");
  Map map1 = { "name": '张三', "age": 18 };
  map1['time'] = '123213';  //添加数据
  map1.addAll({
   'valie':123
  }) //添加数据
  print(map1); { "name": '张三', "age": 18,"time":"123213","valie":123 }
  map1['sex'] = "男";
  print(map1);
  print("---第一个循环方法---");
  // 循环 map
  map1.forEach((key, value) {
    print("$key, $value");
  });

  print("---第二个 Map 循环方法");
  // keys 方法,根据key 值,直接返回对应的value
  for(var key in map1.keys){
    print("$key, ${map1[key]}");
  }

  print("---第三个 Map 循环方法");
  // values 方法, 根据value值,直接返回value,
  for(var value in map1.values){
    print("$value, ${map1[value]}");
  }

  print(map1.containsKey('name')); // 判断 Map 中的键是否存在
  print(map1.containsValue("李四")); // 判断 Map 中的值是否存在

  Map map2 = map1.map((k, v) {
    print('$k,22');
    // 迭代返回一个新的 map
    return MapEntry(v, k);
  });
  print(map2);

  // key values 方法, 根据value值,直接返回value,
  for(var entry in map1.entries){
    print('${entry.key}: ${entry.value}');
  }
  
  //删除指定数据
  map1.remove('name');
}

常量const final

main() {
  const PI = 3.141592653; 						// const定义常量,程序运行之前就知道了值
  final PI2 = 3.141592653;						// 使用const定义的常量也可以使用final来定义
  
  final nowTime = DateTime.now(); 		// final定义常量,需要等到程序第一次运行的时候才能知道值
  
  //const nowTime = DateTime.now(); 	// const是不可以赋值为DateTime.now(),因为编译期DateTime.now()的值不是确定的
}
常量就是值不能改变的
final 关键字定义的常量是在第一次使用时初始化的,初始化后不可改变;
const 关键字定义的常量在编译时就已经被初始化了,永远不会改变。

引号的区别

void main(){
 var a  = '''
  123
  123
 ''';
 print(a);

 var b = '123';
 print(b);
}

三个引号''' ''' 和 单个引号 '' 三个引号可以换行

image.png

字符串拼接

void main(){
 String a = '123';
 String b = '456';
 int c = 0;
 方法1
 print('$a $c $b');
 方法2
 print(a + b + '$c');
}

image.png

条件(if else switch 三目运算符 ?? 跟js使用一样)

var a = 123 var b= '123'
if(a == b) 返回false
区别 对比中不会像js一样

image.png

判断数据类型(is)

void main(){
  var a = '123';
  if(a is String){
    print('进来了额');
  }
}

image.png

算数运算符

main() {
  int a = 10;
  int b = 3;

  print(a + b); 		// 输出 13
  print(a - b); 		// 输出 7
  print(a * b); 		// 输出 30
  print(a / b); 		// 输出 3.3333333333333335
  print(a % b); 		// 输出 1
  print(a ~/ b); 		// 输出 3
}

赋值运算符

void main() {
  int a = 5;
  int b = 3;
  a += b; // a = a + b
  print(a); // 8

  a = 5;
  a -= b; // a = a - b
  print(a); // 2

  a = 5;
  a *= b; // a = a * b
  print(a); // 15
}

自增运算符

void main() {
  int a = 5;
  a++; // a自增1
  print(a); // 输出 6
  a--; // a自减1
  print(a); // 输出 5
}

关系运算符

void main() {
  int a = 10;
  int b = 3;
  print(a == b); // false
  print(a != b); // true
  print(a > b); // true
  print(a < b); // false
  print(a >= b); // true
  print(a <= b); // false
  
  String str = '3';
  print(str == b);	// false,字符串和数字类型是不相等的
}

逻辑运算符

void main() {
  bool a = true;
  bool b = false;
  print(a && b); 		// false
  print(a || b); 		// true
  print(!a); 				// false
  
   dynamic num;
    // bool h = num < 20 || num > 40;
    // print(h);

    num??=23;
    num 为空的时候赋值23
    print(num);
}

判空(isEmpty 针对类型length null '' undefined [] {})

// length null '' undefined [] {}
var k = '';
if(k.isEmpty){
  print('为空');
}

不判空(isNotEmpty)

var k = '';
if(k.isEmpty){
  print('为空');
}

格式转换

数字类型

  void _numType() {
    num num1 = -1.0;
    num num2 = 2;
    int int1 = 3;
    double db1 = 1.68;
    print("num1: $num1 num2: $num2 int1: $int1 db1: $db1");
    print(num1.abs()); // 求绝对值
    print(num1.toInt()); // 转换成init 类型
    print(num1.toDouble()); // 转换成double 类型
    print(num1.toString()); // 转换成String 类型
  }

字符串类型

void main() {
  String str1 = '字符串1', str2 = '字符串2'; // 声明字符串类型
  String str3 = "str1: $str1 str2: $str2"; // 字符串拼接方式1
  String str4 = 'str1' + str1 + ' str2' + str2; // 字符串拼接方式2
  String str5 = "这是字符串类型是的一串文本";
  String str6 = '123'
  // 控制台打印
  print(str3);
  print(str4);
  // 常用方法
  print(int.parse(str6)); //转换成数字类型-整数
  print(double.parse(str6)); //转换成数字类型-浮点
  print(double.tryParse(str6)); //转换成数字类型-不报错 不是数字返回null
  print(str5.substring(1,5)); // 字符串截取
  print(str5.indexOf('类型')); // 获取指定字符串的位置
  print(str5.startsWith("字符串", 2)); // 返回结果:true 判断字符串是否以某字符
  print(str5.startsWith("字符串")); // 返回结果:false 判断字符串是否以某字符
  print(str5.replaceAll('zhe', '替换')); // 返回一个新的字符串,打印结果:替换是字符串类型的一串文本
  print(str5.contains('文本')); // 返回结果:true 判断是否含有文本
  print(str5.split('是')); // 根据指定字符,返回一个数组
}

布尔值

void _boolType () {
    bool bol1 = true, bol2 = false;
    print(bol1 || bol2); // 返回:true
    print(bol1 && bol2); // 返回:false
  }

toList用于将一个集合(如List、Set、Map等)转换为列表)

{1, 2, 3, 4, 5} 输出[1,2,3]
(1,2,3) 输出[1,2,3]

循环

continue 跳过当前循环
break 结束循环
// 集合循环的方式
for(int i=0; i<list3.length; i++){
  if(i == 4){
   continue 跳过当前循环
  }
   if(i == 4){
   break 跳出循环
  }
  print(list3[i]);
}

for(var o in list3){
  print(o);
}

list3.forEach((element) {
  print(element);
});

while

de while

var v = list.map((e) {
  return e + 1;
}).toList();

函数

自定义方法

不指定返回值类型
/**
 * 定义方法,带有命名可选参数
 */
void printUserInfo(String name, {int? age, String? address}) {    // 可选参数可能为空,所以使用?,也可以使用var来定义
  print("姓名:$name");
  if (age != null) {
    print("年龄:$age");
  }
  if (address != null) {
    print("地址:$address");
  }
}

void main() {
  // 命名可选参数,不用考虑参数的位置,根据名称传递
  printUserInfo("张三", address: "北京市", age: 18);

  printUserInfo("李四", age: 20);
}
指定返回值类型
int printUserInfo(String name, {int? age, String? address}) {    // 可选参数可能为空,所以使用?,也可以使用var来定义
  print("姓名:$name");
  if (age != null) {
    print("年龄:$age");
  }
  if (address != null) {
    print("地址:$address");
  }
}

void main() {
  // 命名可选参数,不用考虑参数的位置,根据名称传递
  printUserInfo("张三", address: "北京市", age: 18);

  printUserInfo("李四", age: 20);
}
可选参数
printUserInfo(String name, {int? age, String? address}) {    // 可选参数可能为空,所以使用?,也可以使用var来定义
  print("姓名:$name");
  if (age != null) {
    print("年龄:$age");
  }
  if (address != null) {
    print("地址:$address");
  }
}

printUserInf2(String name, [int? age, String? address]) {    // 可选参数可能为空,所以使用?,也可以使用var来定义
  print("姓名:$name");
  if (age != null) {
    print("年龄:$age");
  }
  if (address != null) {
    print("地址:$address");
  }
}

void main() {
  // 命名可选参数,不用考虑参数的位置,根据名称传递
  printUserInfo("张三", address: "北京市", age: 18);

  printUserInfo("李四", age: 20);
}

{int? age, String? address} 命名可选参数,不用考虑参数的位置,根据名称传递

[int? age, String? address] 命名可选参数,需要考虑参数的位置
带默认值
int printUserInfo(String name, {int? age = 213, String? address}) {    // 可选参数可能为空,所以使用?,也可以使用var来定义
  print("姓名:$name");
  if (age != null) {
    print("年龄:$age");
  }
  if (address != null) {
    print("地址:$address");
  }
}

void main() {
  // 命名可选参数,不用考虑参数的位置,根据名称传递
  printUserInfo("张三", address: "北京市", age: 18);

  printUserInfo("李四", age: 20);
}

匿名函数
const 方法名 = (){}
方法名()
自执行方法
((){
 print('222')
})()
递归 跟js一样

注意 void不一定要写 但是最好写 在方法里面

类的定义和使用

class Student {
  String sid = "001";
  String name = "Doubi";
  int age = 12;

  void study(title) {
    print("我是${this.name}, 我$age岁了, 我在学习${this.title}");
  }
}

void main() {
  Student stu1 = new Student();
  print(stu1.name); // 访问成员变量
  print(stu1.age);
  stu1.study();

  Student stu2 = Student();
  stu2.name = "ShaBi";
  stu2.age = 13;
  stu2.study('2222');
}
构造函数
class Student {
  late String sid;
  String? name;
  late int age;

  // 构造函数
  // Student(String sid, String name, int age) {
  //   this.sid = sid;    // this.sid访问的是属性,sid访问的是形参
  //   this.name = name;
  //   this.age = age;
  // }

  //  构造函数-简写
  Student(this.sid,this.name,this.age);

  void study() {
    print("我是${name}, 我$age岁了, 我在学习");
  }
}

void main() {
  Student stu1 = new Student("001", "Doubi", 12);
  stu1.study();

  Student stu2 = Student("002", "Shabi", 13);
  stu2.study();
}

匿名构造函数

class Student {
  late String sid;
  String? name;
  late int age;

  //  构造函数-简写
  Student.btn(this.sid,this.name,this.age);

  void study() {
    print("我是${name}, 我$age岁了, 我在学习");
  }
}

void main() {
  Student stu1 = new Student.btn("001", "Doubi", 12);
  stu1.study();

  Student stu2 = Student.btn("002", "Shabi", 13);
  stu2.study();
}

私有变量(_ )

当作为方法被外界访问的时候 设置_是不可以被访问的 

class Student {
  late String _sid;
  String? name;
  late int age;

  //  构造函数-简写
  Student.btn(this._sid,this.name,this.age);

  void study() {
    print("我是${name}, 我$age岁了, 我在学习");
  }
}

void main() {
  Student stu1 = new Student.btn("001", "Doubi", 12);
  stu1.study();

  Student stu2 = Student.btn("002", "Shabi", 13);
  stu2.study();
}

get获取值(通过属性获取返回值 实际和函数一样 只是更方便)

class Student {
  late String sid;
  String? name;
  late int age;

  // 构造函数
  // Student(String sid, String name, int age) {
  //   this.sid = sid;    // this.sid访问的是属性,sid访问的是形参
  //   this.name = name;
  //   this.age = age;
  // }

  //  构造函数-简写
  Student(this.sid,this.name,this.age);

  get study {
   return this.sid;
  }
}

void main() {
  Student stu1 = new Student("001", "Doubi", 12);
  var sid = stu1.study;
  print(sid);
}

set设置值

class Student {
  late String sid;
  String? name;
  late int age;

  // 构造函数
  // Student(String sid, String name, int age) {
  //   this.sid = sid;    // this.sid访问的是属性,sid访问的是形参
  //   this.name = name;
  //   this.age = age;
  // }

  //  构造函数-简写
  Student(this.sid,this.name,this.age);

  set study(sid) {
   this.sid = sid
  }
}

初始化的时候设置值

class Student {
  late String sid;
  String? name;
  late int age;

  // 构造函数
   Student(String sid, String name, int age):sid=10,name=10,age=10 {
    this.sid = sid;    // this.sid访问的是属性,sid访问的是形参
    this.name = name;
    this.age = age;
  }

  void study() {
    print("我是${name}, 我$age岁了, 我在学习");
  }
}

void main() {
  Student stu1 = new Student("001", "Doubi", 12);
  stu1.study();

  Student stu2 = Student("002", "Shabi", 13);
  stu2.study();
}

静态方法(static)

    class Student {
      static int stuCount = 0;
      late String sid;
      String? name;
      late int age;

      // 构造函数
      Student(String sid, String name, int age) {
        Student.stuCount++;
        this.sid = sid; // this.sid访问的是属性,sid访问的是形参
        this.name = name;
        this.age = age;
      }

      // 静态方法
      static void getStuCount() {
        print("一共创建了${Student.stuCount}个学生");
      }
      
      // 非静态方法
      static void getStuCount() {
        获取静态属性 print(int)
        获取非静态  print(this.name || name)
      }
    }

    void main() {
      Student("001", "Doubi", 12);
      Student("002", "Shabi", 13);
      Student("002", "ErBi", 14);

      Student.getStuCount();		// 输出: 一共创建了3个学生
    }

    静态方法不需要new 直接调用实例Student 且静态方法不能调用非静态 非静态能调用静态

类继承 extends

class Student {
  String? name;
  String? value;
  Student(String? name,String? value){
    this.name = name;
    this.value = value;
  }
  void role(){
    print("${this.name} ---- ${this.value}");
  }
}

class Web extends Student{
  //super 传递进来的name value 给了父类的name value super代表Student这个构造函数
  Web(name,value):super(name,value){

  }
}

void main() {
  var student = new Web('曹雄','14');
  student.role();
}

类继承 extends 覆写父类方法

class Student {
  String? name;
  String? value;
  Student(String? name,String? value){
    this.name = name;
    this.value = value;
  }
  void role(){
    print("${this.name} ---- ${this.value}");
  }
}

class Web extends Student{
  //super 传递进来的name value 给了父类的name value super代表Student这个构造函数
  Web(name,value):super(name,value){

  }
  //覆写父类方法
  @override
   void role(){
    print("${this.name} --1-- ${this.value}");
  }
}

void main() {
  var student = new Web('曹雄','14');
  student.role();
}

抽象类(约束子类必须要拥有同样的方法 abstract)

比如父亲里有transport 子类继承也必须要有transport
abstract class Vehicle {
  void transport(destination); 抽象方法
    void transport1(){

    }
}

class Web extends Vehicle{
  @override
  void transport(destination) {
    // TODO: implement transport
  }
}

void main() {
 // 抽象类的时候 没办法直接实例化 只能子例进行
  //错误
 //  Vehicle dog1 = new Vehicle();
  //正确
  Web dog = new Web();
}

多态(父亲定义一个方法 让继承的子类去实现 从而让每个子类有不同的表现)

abstract class Vehicle {
  void transport(destination);
}

class Web extends Vehicle{
  @override
  void transport(destination) {
    // TODO: implement transport
  }
}

void main() {
 // 抽象类的时候 没办法直接实例化 只能子例进行
  //错误
 //  Vehicle dog1 = new Vehicle();
  //正确
  Web dog = new Web();
  dog.()
}

接口 (implements定义类型 类似js的ts)

implements 代表Sparrow里面也要有tweet方法

// 定义一个抽象类
abstract class Bird {
  void tweet();
}

class Sparrow implements Bird {
  @override
  void tweet() {
    print("我要呼吸");
  }
}

void main() {
  Animal animal = Sparrow();
  animal.breathe();
}

一个类实现多个接口

// 定义一个抽象类
abstract class Bird {
  void tweet();
}

// 定义一个接口
abstract class Animal {
  void breathe();
}

// 定义一个接口
abstract class Helpful {
  void help();
}

class Sparrow implements Animal, Helpful {
  @override
  void breathe() {
    print("我要呼吸");
  }

  @override
  void tweet() {
    print("我会啾啾叫");
  }

  @override
  void help() {
    print("有益的");
  }
}

混入mix(with)

image.png

..连缀(同一个对象进行一系列的操作 简化操作)

    ..被称为级联操作符(Cascade Notation)。它允许你对同一个对象进行一系列的操作,而不需要重复引用该对象。这种操作符在链式调用方法或设置对象属性时非常有用,可以让代码更加简洁易读。
    var map = {
      'a':123,
      'b':456
    };
    
    map a = '456'
    map b = '567'
    
    ..连缀简化
    map..['a'] = 456
    ..['b'] = 567;
    print(map);

泛型(T 类似js的any)

T getInfo<T>(T value){
   return value;
}

void main() {
  getInfo('123213');
}

泛型类

image.png