PHP开源Hub
致力于开发者的提升

Flutter 基础(三)Dart 快速入门

Flutter基础(三)Dart快速入门

前言

Dart 是 Flutter SDK 指定的语言,因此要学习 Flutter,Dart 是必须掌握的。关于 Dart 可以写一本书了,这里用一篇文章来介绍下 Dart 的精髓,带你快速入门。和 Java 语言类似的部分,这篇文章就尽量不再讲了。

1. Dart 开发环境搭建

学习 Dart 语法最好需要用一个编辑器来实践,这里推荐使用 IntelliJ IDEA。先下载 Dart SDK,地址为:http://www.gekorm.com/dart-windows/
打开 IntelliJ IDEA,菜单中点击 File–>Settings–>plugins,在 plugins 的搜索框中搜索 Dart 并安装,然后重启 IntelliJ IDEA。
点击 File–>New Project–>Dart,按照下图配置 Dart SDK。

1.png

]
注意要选择第三个选项 Constole Application, 否则会默认创建一个 Web 项目。点击 Next 然后配置项目的名称就可以创建项目了。
在项目中的 bin/main.dart 中加入如下测试代码:


void main() {
 print("Hello World");
}

点击菜单的 Run–>Run’main.dart’或者点击工具条的运行图标,就能在控制台看到输出的结果:

2. Dart 概述

Dart 是谷歌开发的计算机编程语言,亮相于 2011 年 10 月,最新的版本是 Dart2。Dart 诞生的原因是谷歌的工程师出于对 JavaScript 的不满,诞生的初期也赢得了部分前端开发者的青睐。但是这时 JavaScript 借着 NodeJS 火了起来,在前端、后端、移动端无孔不入,Dart 就渐渐被人遗忘了,可见 Dart 本身是具有很强的实力的,只是不大走运。谷歌并没有放弃 Dart,不遗余力的推广 Dart:谷歌的 Angular 提供了 Dart 版本,指定 Dart 为新系统 Fuchsia 的官方开发语言,Dart 为移动 UI 框架 Flutter 的开发语言,因此 Dart 又重新回到了人们的视野中。
Dart 通常情况下运行在 DartVM 上,但是在特定情况下它也可以编译成本地代码运行在硬件上,比如 Flutter 会将代码编译成指定平台的本地代码来提高性能。

3. Dart 特性和重要概念

Dart 的特性主要有以下几点:

  1. 执行速度快,Dart 是 AOT (Ahead Of Time) 编译的,可以编译成快速的、可预测的本地代码,这使得 Flutter 几乎都可以使用 Dart 来编写。也可以采用 JIT(Just In Time)编译。
  2. 易于移植,Dart 可编译成 ARM 和 X86 代码,这样 Dart 可以在 Android、iOS 和其他地方运行。
  3. 容易上手,Dart 充分吸收了高级语言特性,如果你已经熟悉 C++、C、Java,可以在短短几天内用 Dart 来开发。
  4. 易于阅读,Dart 使 Flutter 不需要单独的声明式布局语言(XML 或 JSX),或者单独的可视化界面构建器,这是因为 Dart 的声明式编程布局易于阅读。
  5. 避免抢占式调度,Dart 可以在没有锁的情况下进行对象分配和垃圾回收,和 JavaScript 一样,Dart 避免了抢占式调度和共享内存,因此不需要锁。

Dart 的重要概念有以下几点:

  1. 在 Dart 中,一切都是对象,每个对象都是一个类的实例,所有对象都继承自 Object。
  2. Dart 在运行前解析所有的代码,指定数据类型和编译时常量,可以使代码运行的更快。
  3. 与 Java 不同,Dart 不具备关键字 public、protected、private。如果一个标识符以下划线_开始,那么它和它的库都是私有的。
  4. Dart 支持顶级的函数如 main (),也支持类或对象的静态和实例方法,还可以在函数内部创建函数。
  5. Dart 支持顶级的变量,也支持类或对象的静态变量和实例变量,实例变量有时称为字段或属性。
  6. Dart 支持泛型类型,如 List<int>(整数列表)或 List<dynamic>(任何类型的对象列表)。
  7. Dart 工具可以报告两种问题:警告和错误。警告只是说明代码可能无法正常工作,但不会阻止程序执行。错误可以是编译时或运行时的。编译时错误会阻止代码执行;运行时错误会导致代码执行时报出异常。

4. Dart 关键字

关键字
abstract dynamic implements show
as else import static
assert enum in super
async export interface switch
await extends is sync
break external library this
case factory factory factory
catch false new true
class class null try
const finally on typedef
continue for operator var
covariant Function part part
default get rethrow while
deferred hide return with
do if set set

5. 变量

变量声明使用 var 关键字,未初始化的变量的初始值为 null,即便是数字类型的变量也是 null。


var name = 'liuwangshu';

name 变量的类型被推断为 String,也可以显示声明:


String name = 'liuwangshu' ;

如果对象不限于单一类型,可以指定 Object 或 dynamic 类型。


Object name = 'liuwangshu' ;

如果定义的变量不会变化,可以使用 final 或 const 来代替 var,final 变量只能设置一次。


final name = 'liuwangshu'
//name = 'zhangwuji' ; //会报错

const 变量为编译时常量,如果 const 变量在类级别,可以使用 static const。


const pi = 3.1415926; 
const area = pi * 60 * 60;

const 不仅仅用来定义常量,也可以使用 const 来创建常量的值。


var foo = const []; final bar = const []; const baz = [];//相当于`const []`

6. 基本数据类型

Dart 的基本数据类型包括 Number、String、Boolean、List、Set、Map、 Symbol、Runes。

6.1 Number

number 类型为两类:

  • int:整数值不大于 64 位,具体取决于平台。在 Dart VM 上,值可以是 – 2 ^63 到 2 ^63 – 1,如果编译为 JavaScript,允许值为 – 2^53 to 2^53 – 1。
  • double:64-bit (双精度) 浮点数,符合 IEEE 754 标准。

6.2 String

Dart 字符串是 UTF-16 编码的字符序列。 可以使用单引号或者双引号来创建字符串:


var s1 = '单引号适用于字符串文字';
var s2 = "双引号同样有效";

可以在字符串中使用表达式,用法是: ${expression}。如果表达式是一个标识符,可以省略 {}。


var s = '乾坤大挪移';
assert('张无忌的$s' ==
 '张无忌的乾坤大挪移');

使用三个单引号或者三个双引号可以创建多行字符串对象:


var s1 = '''
第一行
第二行
''';

var s2 = """第一行
第二行""";

6.3 Boolean

Dart 是强 bool 类型检查,只有 true 对象才被认为是 true。


var name = '张无忌';
if (name) {
 print('明教教主');
}

上面的代码编译不能通过,因为 name 是一个字符串,而不是 bool 类型。

6.4 List

下面是一个 List 的示例:


var list = [1, 2, 3];

List 的第一个元素的索引是 0,最后一个元素的索引是 list.length – 1 。


var list = [1, 2, 3, 4, 5, 6];
print(list.length);
print(list[list.length-1]);

6.5 Set

Dart 中的 Set 是一组无序的集合。


var hero = ['张无忌', '风清扬', '张三丰', '独孤求败', '萧峰'];

要创建一个空集,可以在 {} 前面带有类型参数:


var heros= <String> {};

使用 add () 或 addAll () 方法将条目添加到现有集中:


var heros = <String>{};
heros.add('石破天');
heros.addAll(hero);

6.6 Map

Map 是一个键值对相关的对象,键和值可以是任何类型的对象,每个键都是唯一的,而一个值则可以出现多次。


var player= {
// Keys      Values
 '20' : '斯诺',
 '3': '艾弗森',
 '40' : '希尔',
 '8' : '麦基',
 '55' : '穆托姆博'
};

使用 Map 构造函数也可以实现同样的功能:


var player = new Map();
player['20'] = '斯诺';
player['3'] = '艾弗森';
player['40'] = '希尔';

7. 函数

Dart 是一个真正面向对象的语言,函数属于 Function 对象。这意味着,函数可以赋值给变量,也可以当做其他函数的参数。


void printName(String name) {
 print('name is $name');
}

7.1 可选参数

可选参数可以是可选位置参数,也可以是可选命名参数,但不能同时使用。

可选命名参数
调用方法的时候,可以使用 paramName: value 的形式来指定参数的名称,这样就可以根据 paramName 得知参数的含义,提高代码的可读性。


coffeeFlavor (sugar :true ,sugar :false );

定义函数时,使用 {param1, param2, …} 的形式来指定命名参数:


coffeeFlavor ({bool sugar , bool sugar}) {

}

可选位置参数
把函数的参数放到 [] 中就变成可选位置参数了:


String go(String to, [String who]) {
 var result = 'go to the $to';
 if (who != null) {
 result = '$result with $who';
 }
 return result;
}

7. 2 默认参数值

可以使用 = 来定义可选参数的默认值, 默认值必须是编译时常量。 如果没有提供默认值,则默认值为 null。


String go(String to, [String who= 'liuwangshu']) {
 var result = 'go to the $to';
 if (who != null) {
 result = '$result with $who';
 }
 return result;
}
 String result= go ('beijing');

7.3 main 函数

每个应用都需要有个顶级的 main () 函数来作为入口才能执行。 main () 函数的返回值为 void 并且有个可选的 List<String> 参数。此前我们举的例子都是在 main 函数中运行才能得已验证:


void main(){
 void printName(String name) {
 print('name is $name');
 }
 printName('liuwangshu');
}

7.4 匿名函数

大部分函数都有名字,例如 main () 或者 printElement ()。 可以创建没有名字的匿名方法,格式如下所示。


([[Type] param1[,]]) { 
 codeBlock; 
};

下面的代码定义了一个参数为 i(该参数没有指定类型)的匿名函数。 list 中的每个元素都会调用这个函数打印出来.


var list = ['张无忌', '风清扬', '张三丰', '独孤求败', '萧峰'];
list.forEach((i) {
 print(list.indexOf(i).toString() + ': ' + i);
});

8. 流程控制语句

Dart 的流程控制语句如下:

  • if 和 else
  • for 循环
  • while 和 do- while 循环
  • break 和 continue
  • switch 和 case
  • assert

这些语句的大部分都和 Java 差不多,这里主要讲解 for 循环和 switch 语句。

8.1 for 循环

标准的 for 循环:


var message = new StringBuffer("张无忌");
for (var i = 0; i < 3; i++) {
 message.write('!');
}

List 和 Set 等实现了 Iterable 接口的类还支持 for-in 形式的遍历:


var hero = ['张无忌', '风清扬', '张三丰', '独孤求败', '萧峰'];
for (var h in hero) {
 print(h);
}

8.2 switch 和 case

Dart 中 Switch 语句通过使用 == 来比较整型、字符串或者编译时常量。被比较的对象必须都是同一个类的实例(不能是其子类),并且这个类不允许覆写 ==。另外,枚举类型很适用于在 Switch 语句使用。\


String today='Friday';
switch(today){
 case 'Monday':
 print('星期一');
 break;
 case 'Friday':
 print('星期五');
 break;
}

9. 捕获异常

捕获异常可以避免异常继续传递。


try {
 //...
} on OutOfLlamasException {
 //...
} on Exception catch (e) {
 print('Unknown exception: $e');
} catch (e) {
 print('Something really unknown: $e');
}

使用 on 或者 catch 来声明捕获语句,也可以同时使用。其中 on 来指定异常类型,catch 来捕获异常对象。
确保某些代码不管有没有出现异常都会执行,可以使用 finally 语句来实现。


try {
 //...
} catch(e) {
 print('Error: $e'); 
} finally {
 //...
}

10. 为类添加新的功能

Dart 是一个面向对象编程语言,支持基于 Mixin 的继承机制。Mixin 可以理解为多继承,在 with 关键字的后面为一个或者多个类。


class Person{
 run(){
 print('跑');
 }
}

class Wushu{
 use(){
 print('乾坤大挪移');
 }
}

class Zhangwuji extends Person with Wushu{
int age;
Zhangwuji(int age){
 this.age=age;
 }
}

void main() {
 var zhangwuji=new Zhangwuji(30);
 zhangwuji.run();
 zhangwuji.use();
}

通过如上代码的验证,Zhangwuji 类拥有了 Person 和 Wushu 这两个类的方法。

11. 库的使用

使用 import 来引入一个库,对于 Dart 语言内置的库,使用 dart: scheme。 对于第三方的库,可以使用文件系统路径或者 package: scheme。


import 'dart:io';
import 'package:mylib/mylib.dart';
import 'package:utils/utils.dart';

指定库前缀
如果导入的两个库具有冲突的名字, 可以使用库的前缀来进行区分。 例如,如果 library1 和 library2 都有一个名字为 Element 的类,可以这样使用:


import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// ...
Element element1 = new Element();           //使用lib1中的Element
lib2.Element element2 = new lib2.Element(); //使用lib2中的Element

导入库的一部分
如果只使用库的一部分功能,则可以选择需要导入的部分内容。其中 show 代表只导入指定的部分,hide 代表除了指定的部分都导入。


// 只导入foo
import 'package:lib1/lib1.dart' show foo;

// 除了foo,其他部分都导入
import 'package:lib2/lib2.dart' hide foo;

延迟加载库
延迟加载意味着应用程序可以在需要的时候再加载库,使用延迟加载库的场景主要有以下几点:

  • 减少 APP 的初始启动时间。
  • 执行 A/B 测试,例如尝试各种算法的不同实现。
  • 加载很少使用的功能。

要延迟加载一个库,需要先使用 eferred as 来导入:


import 'package:deferred/hello.dart' deferred as hello;

当需要使用的时候,调用 loadLibrary () 函数来加载库:


greet() async {
 await hello.loadLibrary();
 hello.printGreeting();
}

12. 异步支持

Dart 库中包含许多返回 Future 或 Stream 对象的函数。这些函数是异步的,它们在基本操作后会返回,而不等待该操作完成,例如读取一个文件,在打开文件后就返回了。
虽然看起来有点像同步代码,但是 async 和 await 的代码是的确异步的。


await readFile()

要使用 await,其方法必须带有 async 关键字:


FileOperate() async {
var file= await readFile()
//其他处理
}

13. 让类可调用

如果 Dart 中的类实现了 call () 函数,那么这个类可以当做方法来调用。


class JointFunction {
 call(String a, String b, String c, String d) => '$a $b $c $d';
}

main() {
 var jf = new JointFunction();
 var out = jf("放","手","去","做");//1
 print('$out');
}

在下面的示例中,JointFunction 类定义了一个 call () 函数,它接收三个字符串并拼接它们。这样在注释 1 处就可以调用 JointFunction 类了。

14. 创建实例

在 Java 中创建实例可以用 new,在 Dart 中你可以选择用 new,也可以选择不用:


Element element = Element();

对于 Android 开发来说用 new 可能更习惯一些,可读性也稍微好点,不用 new 的话显得更简洁,至于用不用 new 就看团队的要求和个人的习惯吧,没有绝对的好坏之分。

总结

Dart 的知识点有很多,这里只介绍了一部分我认为需要重点掌握的部分,如果想了解更多,可以查看官方文档,关于 Dart 的学习可以结合 Flutter 边写边学,不要只抠 Dart 的细节。

赞(2) 打赏
未经允许不得转载PHP开源Hub » Flutter 基础(三)Dart 快速入门

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

PHP开源Hub-致力于互联网开发者的成长

技术群聊软文发表

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏