Dart语言精简入门介绍

Dart语言精简入门介绍

1、介绍

  • Dart 在设计时应该是同时借鉴了 Java 和 JavaScript和kotlin

  • 面向对象

  • JIT&AOT:JIT(Just in Time)优点:即时编译,开发期间更快编译,更快的重载;缺点:在运行时将代码编译成机器码,给用户最直接的感受就是慢;AOT(Ahead Of Time)事前编译,release期间更快更流畅,典型的例子就是C和C++,它能够直接编译机器码即二进制代码,所以它的加载和执行速度是非常快的。你会发现在开发期间安装Flutter的时候会有一些卡顿,但是在release就是发布之后会变好,这种模式使得APP在发布之后能够以更快的速度运行。

2、基本数据类型

  • 数字类型(num、int和double)

    1)、num:

    Dart数字类型的父类,它既接受浮点类型,也接受整数类型

    num num1 = -1.0; //num是数字类型的父类
    num num2 = 2; //num是数字类型的父类
    

    2)、int、double

    num有两个子类,一个是int,一个是double,int类型只能接收整数,double类型是双精度

    int int1 = 3; //子类一 int类型 只能接收整数
    double d1 = 2.22; //子类二 双精度
    
  • 字符串(String)

    在dart中定义字符串可以用单引号也可以用双引号,一行可以定义一个字符串,也可以定义多个字符串,中间用逗号隔开:

    String str1 = '字符串', str2 = "双引号字符串"; //字符串的定义
    

    在dart中如何进行字符串拼接直接使用加号“+”拼接,当然还有另外一种方法,在上面数字类型的讲解中也有使用到,我们可以使用"$"加上变量名去引用一个变量,这个变量可以是数字类型当然也可以是字符串类型,这个和kotlin语言有点像

    String str3 = 'str1:$str1 str2:$str2'; //字符串拼接
    String str4 = 'str1:' + str1 + "str2:" + str2; //字符串拼接
    String s = "this is dart2";
    String s2 = 'this is dart2';
    // 使用==判断字符串是否相等
    print(s == s2); // true
    

    字符串的方法和java里面的字符串方法类似

  • 布尔

    Dart是强bool类型检查,只有bool类型的值是true,才被认为是true

  • 集合之List

    在Dart中定义集合使用List关键字,List表明集合是个泛型,这里可以传入任何数据类型。List集合可以使用“[]”进行初始化,例如:List list = [1,2,‘测试’]; 这种形式,这里没使用泛型所以中括号里面添加元素时既可以传入数字也可以传入字符串,如果需要指定泛型类型,例如:List list1 = []; 这种形式下,添加元素的时候只能添加int类型的数据。

    List list = [1, 2, 3, '集合']; //初始化添加元素
    List list3 = [];
    list3.add('list3'); //通过add方法添加元素
    list3.addAll(list);
    print(list3);
    

    List集合的遍历

    第一种:没有语言之分的for循环方式:

    for (int i = 0; i < list.length; i++) {print(list[i]);
    }
    

    第二种:for…in…,同样是for,但是表达式内部我们做一点修改,使用var关键字定义一个变量,然后使用in关键字在集合中进行遍历:

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

    第三种:forEach()循环,将函数应用于集合的每个元素,括号内传入的为集合的元素:

    list.forEach((val) {print(val);
    });
    
  • 集合之Map

    Map集合的初始化

    Map是将key和value相关联的对象,key和value都可以是任意类型的对象,并且key是唯一的,如果key重复,后面添加的key会替换前面的内容。

    ///Map初始化
    Map names = {'xiaoming': '小明', "xiaohong": "小红"};
    print(names);
    Map ages = {};
    ages['xiaoming'] = 12;
    ages['xiaohong'] = 18;
    print(ages);
    

    Map的遍历

    它的里面需要一个回调函数,回调函数里面会输出我们的key和value

    ///Map遍历方式
    ages.forEach((k, v) {print('$k,$v');
    });
    

    map()方法,我们可以调用Map集合的map()方法遍历生成一个新的map集合,这个方法接收一个回调函数,入参为key、value,函数内部必须接受一个return,也就是说它会返回一个新的map,这里通过MapEntry来返回之前Map里面每一项的元素,我这里将原map的key和value进行颠倒,那么就可以得到一个相反的集合

    Map ages2 = ages.map((k, v) {return MapEntry(v, k);
    });
    print(ages2);
    

    第三种:for循环

    首先循环遍历map集合中所有的key,可以通过map.keys获取,它返回的是一个所有key值的数组(同样的也有map.values),然后我们就可以通过map[key]获取集合中的每一个元素了,代码如下:

    for (var key in ages.keys) {print('$key , ${ages[key]}');
    }
    

3、变量声明

  • var

    类似于 JavaScript 中的var,它可以接收任何类型的变量,但最大的不同是 Dart 中 var 变量一旦赋值,类型便会确定,则不能再改变其类型,如:

    var t = "hi world";
    // 下面代码在dart中会报错,因为变量t的类型已经确定为String,
    // 类型一旦确定后则不能再更改其类型。
    t = 1000;
    
  • dynamicObject

    Object 是 Dart 所有对象的根基类,也就是说在 Dart 中所有类型都是Object的子类(包括Function和Null),所以任何类型的数据都可以赋值给Object声明的对象。 dynamicObject声明的变量都可以赋值任意对象,且后期可以改变赋值的类型,这和 var 是不同的,如:

    dynamic t;
    Object x;
    t = "hi world";
    x = 'Hello Object';
    //下面代码没有问题
    t = 1000;
    x = 100
    

    dynamicObject不同的是dynamic声明的对象编译器会提供所有可能的组合,而Object声明的对象只能使用 Object 的属性与方法, 否则编译器会报错

     dynamic a;Object b = "";main() {a = "";printLengths();}   printLengths() {// 正常print(a.length);// 报错 The getter 'length' is not defined for the class 'Object'print(b.length);}
    

4、常量和空安全

  • finalconst

    如果您从未打算更改一个变量,那么使用 finalconst,不是var,也不是一个类型。 一个 final 变量只能被设置一次,两者区别在于:const 变量是一个编译时常量(编译时直接替换为常量值),final变量在第一次使用时被初始化。被final或者const修饰的变量,变量类型可以省略

    //可以省略String这个类型声明
    final str = "hi world";
    //final String str = "hi world"; 
    const str1 = "hi world";
    //const String str1 = "hi world";
    
  • 空安全(null-safety)

    Dart 中一切都是对象,这意味着如果我们定义一个数字,在初始化它之前如果我们使用了它,假如没有某种检查机制,则不会报错,比如:

    test() {int i; print(i*8);
    }
    

    在 Dart 引入空安全之前,上面代码在执行前不会报错,但会触发一个运行时错误,原因是 i 的值为 null 。但现在有了空安全,则定义变量时我们可以指定变量是可空还是不可空。

    int i = 8; //默认为不可空,必须在定义时初始化。
    int? j; // 定义为可空类型,对于可空变量,我们在使用前必须判空。// 如果我们预期变量不能为空,但在定义时不能确定其初始值,则可以加上late关键字,
    // 表示会稍后初始化,但是在正式使用它之前必须得保证初始化过了,否则会报错
    late int k;
    k=9;
    

    如果一个变量我们定义为可空类型,在某些情况下即使我们给它赋值过了,但是预处理器仍然有可能识别不出,这时我们就要显式(通过在变量后面加一个”!“符号)告诉预处理器它已经不是null了,比如:

    class Test{int? i;Function? fun;say(){if(i!=null) {print(i! * 8); //因为已经判过空,所以能走到这 i 必不为null,如果没有显式申明,则 IDE 会报错}if(fun!=null){fun!(); // 同上}}
    }
    

    上面中如果函数变量可空时,调用的时候可以用语法糖:

    fun?.call() // fun 不为空时则会被调用
    

    这里和kotlin有点类似

5、函数

Dart是一种真正的面向对象的语言,所以即使是函数也是对象,并且有一个类型Function。这意味着函数可以赋值给变量或作为参数传递给其他函数,这是函数式编程的典型特征。

  • 函数声明

    bool isNoble(int atomicNumber) {return _nobleGases[atomicNumber] != null;
    }
    

    这里函数声明跟java或javascript有点类似

    对于只包含一个表达式的函数,可以使用简写语法:

    bool isNoble (int atomicNumber)=> true ;   
    
  • 函数作为变量

    var say = (str){print(str);
    };
    say("hi world");
    
  • 函数作为参数传递

    void execute(var callback) {callback();
    }
    execute(() => print("xxx"))
    
  • 可选的位置参数

    String say(String from, String msg, [String device]) {var result = '$from says $msg';if (device != null) {result = '$result with a $device';}return result;
    }
    say('Bob', 'Howdy'); //结果是: Bob says Howdy
    say('Bob', 'Howdy', 'smoke signal'); //结果是:Bob says Howdy with a smoke signal
  • 可选的命名参数

    定义函数时,使用{param1, param2, …},放在参数列表的最后面,用于指定命名参数。例如:

    //设置[bold]和[hidden]标志
    void enableFlags({bool bold, bool hidden}) {// ... 
    }
    

    调用函数时,可以使用指定命名参数。例如:paramName: value

    enableFlags(bold: true, hidden: false);
    

    可选命名参数在Flutter中使用非常多。注意,不能同时使用可选的位置参数和可选的命名参数

6、类和继承

Dart中的继承:

1.子类使用extends关键词来继承父类

2.子类会继承父类里面可见的属性和方法,但是不会继承构造函数

3.子类能复写父类的方法 getter和setter

4.Dart 是不支持多继承的,类和接口是统一的,类就是接口。

一般情况使用抽象类作为接口

void main() {new Student().run();
}abstract class Person {void run();
}class Student implements Person {@overridevoid run() {print("....");}
}

7、异步的支持

Dart类库有非常多的返回Future或者Stream对象的函数。 这些函数被称为异步函数:它们只会在设置好一些耗时操作之后返回,比如像 IO操作。而不是等到这个操作完成。

  • Future

    Future与JavaScript中的Promise非常相似,表示一个异步操作的最终完成(或失败)及其结果值的表示。简单来说,它就是用于处理异步操作的,异步处理成功了就执行成功的操作,异步处理失败了就捕获错误或者停止后续操作。一个Future只会对应一个结果,要么成功,要么失败。

    由于本身功能较多,这里我们只介绍其常用的API及特性。还有,请记住,Future 的所有API的返回值仍然是一个Future对象,所以可以很方便的进行链式调用

    1)、Future.then

    为了方便示例,在本例中我们使用Future.delayed 创建了一个延时任务(实际场景会是一个真正的耗时任务,比如一次网络请求),即2秒后返回结果字符串"hi world!",然后我们在then中接收异步结果并打印结果,代码如下:

    Future.delayed(Duration(seconds: 2),(){return "hi world!";
    }).then((data){print(data);
    });
    

    2)、Future.catchError

    Future.delayed(Duration(seconds: 2),(){//return "hi world!";throw AssertionError("Error");  
    }).then((data){//执行成功会走到这里  print("success");
    }).catchError((e){//执行失败会走到这里  print(e);
    });
    

    3)、Future.whenComplete

    有些时候,我们会遇到无论异步任务执行成功或失败都需要做一些事的场景,比如在网络请求前弹出加载对话框,在请求结束后关闭对话框。这种场景,有两种方法,第一种是分别在thencatch中关闭一下对话框,第二种就是使用FuturewhenComplete回调,我们将上面示例改一下:

    Future.delayed(Duration(seconds: 2),(){//return "hi world!";throw AssertionError("Error");
    }).then((data){//执行成功会走到这里 print(data);
    }).catchError((e){//执行失败会走到这里   print(e);
    }).whenComplete((){//无论成功或失败都会走到这里
    });
    

    4)、Future.wait

    有些时候,我们需要等待多个异步任务都执行结束后才进行一些操作,比如我们有一个界面,需要先分别从两个网络接口获取数据,获取成功后,我们需要将两个接口数据进行特定的处理后再显示到UI界面上,应该怎么做?答案是Future.wait,它接受一个Future数组参数,只有数组中所有Future都执行成功后,才会触发then的成功回调,只要有一个Future执行失败,就会触发错误回调。下面,我们通过模拟Future.delayed 来模拟两个数据获取的异步任务,等两个异步任务都执行成功时,将两个异步任务的结果拼接打印出来,代码如下:

    Future.wait([// 2秒后返回结果  Future.delayed(Duration(seconds: 2), () {return "hello";}),// 4秒后返回结果  Future.delayed(Duration(seconds: 4), () {return " world";})
    ]).then((results){print(results[0]+results[1]);
    }).catchError((e){print(e);
    });
    

    执行上面代码,4秒后你会在控制台中看到“hello world”。

    5)、Async/await

    如果代码中有大量异步逻辑,并且出现大量异步任务依赖其它异步任务的结果时,必然会出现Future.then回调中套回调情况。举个例子,比如现在有个需求场景是用户先登录,登录成功后会获得用户ID,然后通过用户ID,再去请求用户个人信息,获取到用户个人信息后,为了使用方便,我们需要将其缓存在本地文件系统,代码如下:

    //先分别定义各个异步任务
    Future<String> login(String userName, String pwd){...//用户登录
    };
    Future<String> getUserInfo(String id){...//获取用户信息 
    };
    Future saveUserInfo(String userInfo){...// 保存用户信息 
    }; 
    

    接下来,执行整个任务流:

    login("alice","******").then((id){//登录成功后通过,id获取用户信息    getUserInfo(id).then((userInfo){//获取用户信息后保存 saveUserInfo(userInfo).then((){//保存用户信息,接下来执行其它操作...});});
    })
    

    消除嵌套

    login("alice","******").then((id){return getUserInfo(id);
    }).then((userInfo){return saveUserInfo(userInfo);
    }).then((e){//执行接下来的操作 
    }).catchError((e){//错误处理  print(e);
    });
    

    使用 async/await 消除嵌套

    task() async {try{String id = await login("alice","******");String userInfo = await getUserInfo(id);await saveUserInfo(userInfo);//执行接下来的操作   } catch(e){//错误处理   print(e);   }  
    }
    
    • async用来表示函数是异步的,定义的函数会返回一个Future对象,可以使用 then 方法添加回调函数。

    • await 后面是一个Future,表示等待该异步任务完成,异步完成后才会往下走;await必须出现在 async 函数内部。

  • Stream

    Stream 也是用于接收异步事件数据,和 Future 不同的是,它可以接收多个异步操作的结果(成功或失败)。 也就是说,在执行异步任务时,可以通过多次触发成功或失败事件来传递结果数据或错误异常。 Stream 常用于会多次读取数据的异步任务场景,如网络内容下载、文件读写等。举个例子:

Stream.fromFutures([// 1秒后返回结果Future.delayed(Duration(seconds: 1), () {return "hello 1";}),// 抛出一个异常Future.delayed(Duration(seconds: 2),(){throw AssertionError("Error");}),// 3秒后返回结果Future.delayed(Duration(seconds: 3), () {return "hello 3";})
]).listen((data){print(data);
}, onError: (e){print(e.message);
},onDone: (){});

上面的代码依次会输出:

I/flutter (17666): hello 1
I/flutter (17666): Error
I/flutter (17666): hello 3

参考链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/285598.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WPF 窗口居中 变更触发机制

本文经原作者授权以原创方式二次分享&#xff0c;欢迎转载、分享。原文作者&#xff1a;唐宋元明清原文地址&#xff1a;https://www.cnblogs.com/kybs0/p/7420767.html窗口居中 & 变更触发机制解决&#xff1a;1&#xff09;单实例窗口&#xff0c;窗口每次隐藏后再显示时…

[转]5分钟实现Android中更换头像功能

5分钟实现Android中更换头像功能 写在前面&#xff1a; 更换头像这个功能在用户界面几乎是100%出现的。通过拍摄照片或者调用图库中的图片&#xff0c;并且进行剪裁&#xff0c;来进行头像的设置。 功能相关截图如下&#xff1a; 下面我们直接看看完整吧&#xff1a; public cl…

Excel VBA窗体上打印系统时间print now出错原因及解决方案

如图所示,需要在窗体上显示当前系统时间: 首先,我们看一下now函数的原型: Now 函数   语法:Now   说明:返回一个 Variant (Date),根据计算机系统设置的日期和时间来指定日期和时间。   示例: Private Sub CommandButton1_Click()Dim a As Varianta = NowMsgBox…

(第九周)团队项目14

项目名&#xff1a;食物链教学工具 组名&#xff1a;奋斗吧兄弟 组长&#xff1a;黄兴 组员&#xff1a;李俞寰、杜桥、栾骄阳、王东涵 代码地址&#xff1a;HTTPS: https://git.coding.net/li_yuhuan/FoodChain.git SSH: gitgit.coding.net:li_yuhuan/FoodChain.git SCRUM会议…

为什么 C# 访问 null 字段会抛异常?

一&#xff1a;背景 1. 一个有趣的话题最近在看 硬件异常 相关知识&#xff0c;发现一个有意思的空引用异常问题&#xff0c;拿出来和大家分享一下&#xff0c;为了方便讲述&#xff0c;先上一段有问题的代码。namespace ConsoleApp2 {internal class Program{static Person pe…

Android项目实战(十五):自定义不可滑动的ListView和GridView

不可滑动的ListView (RecyclweView类似) public class NoScrollListView extends ListView {public NoScrollListView(Context context, AttributeSet attrs) {super(context,attrs);}public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){ int mExpandSpec …

C语言试题一百之输入某年某月某日,判断这一天是这一年的第几天

✅作者简介:大家好我是码莎拉蒂,CSDN博客专家🥇🥇🥇 📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 1、题目 题目:输入某年某月某日,判断这一天是这一年的第几天? 分析: 以 3 月 5 日为例,应该先把…

[转]Java学习路线图(完整详细2019版)

一门永不过时的编程语言——Java 软件开发。 Java编程语言占比&#xff1a; 据官方数据统计&#xff0c;在全球编程语言工程师的数量上&#xff0c;Java编程语言以1000万的程序员数量位居首位。 而且很多软件的开发都离不开Java编程&#xff0c;因此其程序员的数量最多。而在…

【CASS精品教程】Win7+CAD2008+CASS9.1(含CASS3D)完美安装教程(附完整软件安装包下载)

本文讲解win764位系统上安装CAD2008+CASS9.1(含CASS3D)免费版安装,文末附完整软件下载地址,亲测可用!!! 文章目录 1. CAD2008安装2. CASS9.1安装3. 软件下载地址1. CAD2008安装 双击安装包中的Setup.exe,开始安装。 点击【安装产品】。

(十一)Jmeter另一种调试工具 HTTP Mirror Server

之前我介绍过Jmeter的一种调试工具Debug Sampler&#xff0c;它可以输出Jmeter的变量、属性甚至是系统属性而不用发送真实的请求到服务器。既然这样&#xff0c;那么HTTP Mirror Server又是做什么用的呢&#xff1f; 一、HTTP Mirror Server的作用&#xff1a; 它可以在本地临…

C语言九十八之实现企业发放的奖金根据利润提成。利润(I)低于或等于 10 万元时,奖金可提 10%;利润高 于 10 万元,低于 20 万元时,低于 10 万元的部分按 10%提成,高于 10 万元的

✅作者简介:大家好我是码莎拉蒂,CSDN博客专家🥇🥇🥇 📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 1、题目 企业发放的奖金根据利润提成。利润(I)低于或等于 10 万元时,奖金可提 10%;利润高 于 10 万…

[转]大数据环境搭建步骤详解(Hadoop,Hive,Zookeeper,Kafka,Flume,Hbase,Spark等安装与配置)

大数据环境安装和配置&#xff08;Hadoop2.7.7&#xff0c;Hive2.3.4&#xff0c;Zookeeper3.4.10&#xff0c;Kafka2.1.0&#xff0c;Flume1.8.0&#xff0c;Hbase2.1.1&#xff0c;Spark2.4.0等&#xff09; 系统说明搭建步骤详述 一、节点基础配置 二、Hadoop安装和配置三、…

C# Any()和AII()方法

我们常常需要的另一类查询是确定数据是否满足某个条件&#xff0c;或者确保所有数据都满足某个条件。例如&#xff0c;需要确定某个产品是否已经脱销(库存为 0)&#xff0c;或者是否发生了某个交易。LINQ 提供了两个布尔方法&#xff1a;Any()和 All()&#xff0c;它们可以快速…

树状数组 + 位运算 LA 4013 A Sequence of Numbers

题目传送门 题意&#xff1a;n个数&#xff0c;两种操作&#xff0c;一是每个数字加x&#xff0c;二是查询& (1 << T) 1 的个数 分析&#xff1a;因为累加是永远的&#xff0c;所以可以离线处理。树状数组点是c[16][M] 表示数字x%(1 << j) 后的数字pos&#x…

【地理信息系统GIS】教案(七章全)第七章:3S技术综合应用

文章目录 第一节 3S技术概述第二节 GIS与RS的综合应用第三节 GIS与GPS的综合应用第四节 网络GIS的综合应用第一节 3S技术概述 1.什么是“3S” 技术? 遥感(Remote Sensing ,RS); 地理信息系统(Geographical information System ,GIS); 全球定位系统(Global Positio…

初级图像混合——线性混合操作

addWeighted函数 这个函数的作用是&#xff0c;计算两个数组&#xff08;图像阵列&#xff09;的加权和。原型如下&#xff1a; void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype-1); 第一个参数&am…

C语言九十九之实现一个整数,它加上 100 后是一个完全平方数,再加上 168 又是一个完全平方数,请问该数是多少?

✅作者简介:大家好我是码莎拉蒂,CSDN博客专家🥇🥇🥇 📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 一、题目 一个整数,它加上 100 后是一个完全平方数,再加上 168 又是一个完全平方数,请问该数是多…

【专升本计算机】2021年甘肃省专升本计算机全真模拟试题(一)

【专升本计算机】2021年甘肃省专升本计算机全真模拟试题(一) 【专升本计算机】2021年甘肃省专升本计算机全真模拟试题(二) 【专升本计算机】2021年甘肃省专升本计算机全真模拟试题(三) 【专升本计算机】2021年甘肃省专升本计算机全真模拟试题(四) 【专升本计算机】2021…

快速掌握 ASP.NET 身份认证框架 Identity - 通过邮件重置密码

这是 ASP.NET Core Identity 系列的第四篇文章&#xff0c;上一篇文章讲解了如何在 ASP.NET Core Identity 中实现用户登录与登出。这篇文章讲一讲如何在 ASP.NET Core Identity 中通过邮件服务实现用户账号的密码重置。点击上方或后方蓝字&#xff0c;阅读 ASP.NET Core Ident…

[.net 面向对象程序设计深入](4)MVC 6 —— 谈谈MVC的版本变迁及新版本6.0发展方向...

[.net 面向对象程序设计深入]&#xff08;4&#xff09;MVC 6 ——谈谈MVC的版本变迁及新版本6.0发展方向 1.关于MVC 在本篇中不再详细介绍MVC的基础概念&#xff0c;这些东西百度要比我写的全面多了&#xff0c;MVC从1.0到5.0的时间也不短了&#xff0c;很多人只是按照范例去使…