Flutter基础(三)Dart快速入门

本文首发于微信公众号「刘望舒」html

前言

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

1. Dart开发环境搭建

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

注意要选择第三个选项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的特性主要有如下几点:express

  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。json

var name = 'liuwangshu';
复制代码

name变量的类型被推断为String,也能够显示声明:windows

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就看团队的要求和我的的习惯吧,没有绝对的好坏之分。

Flutter基础系列
Flutter基础(一)移动开发的跨平台技术演进
Flutter基础(二)Flutter开发环境搭建和Hello World
Flutter基础(三)Dart快速入门
Flutter基础(四)开发Flutter应用前须要掌握的Basic Widget
Flutter基础(五)Material组件之MaterialApp、Scaffold、AppBar
Flutter基础(六)Material组件之BottomNavigationBar、TabBar、Drawer
Flutter基础(七)Scrolling Widget之ListView、GridView、PageView
Flutter基础(八)手势相关Widget:GestureDetector和Dismissible
Flutter基础(九)资源和图片
Flutter基础(十)布局Widget快速入门
Flutter基础(十一)网络请求(Dio)与JSON数据解析
Flutter基础(十二)路由(页面跳转)与数据传递
Flutter基础(十三)Flutter与Android的相互通讯

总结

Dart的知识点有不少,这里只介绍了一部分我认为须要重点掌握的部分,若是想了解更多,能够查看官方文档,关于Dart的学习能够结合Flutter边写边学,不要只抠Dart的细节。


分享大前端、Android、Java等技术,助力5万程序员成长进阶。

相关文章
相关标签/搜索