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萬程序員成長進階。

相關文章
相關標籤/搜索