flutter-dart菜鳥入門

flutter-dart菜鳥入門

本人是一名Android開發,這是我的在學習flutter的過程當中對dart的一些學習總結和本身的理解,若是發現什麼寫的不對的地方,請勿噴java

本文只是簡單介紹開發flutter的dart的經常使用用法,強烈建議閱讀官方文檔dart中文網地址es6

1. 爲何要介紹dart?

由於 Flutter 須要使用Dart語言開發;express

2. 基本數據類型

  • num 數字, 包括整數和浮點數
  • int 整數
  • double 浮點數
  • String 字符串
  • bool 布爾值

3. 重要的概念

  • dart全部對象類都繼承 Object
  • dart全部變量都是對象,包括數字、null等都是對象
  • dart全部類型變量的默認值全是null(包括數字類型和布爾類型)
  • dart跟Java不一樣,沒有 public、 protected、 和 private 修飾符;私有變量以 (_) 開頭,不然是就是公有的
  • 當dart 須要一個布爾值的時候,只有 true 對象才被認爲是 true,其餘任何狀況都是false,這點和 JavaScript 不同
  • dart支持高階函數、頂級函數、頂級變量、靜態函數、靜態變量等

4. 定義變量

用var定義一個可變類型的變量json

var name = 'Bob';
name = 1;
name = false;
複製代碼

定義具體類型的變量數組

String name = 'Bob'; // 定義一個字符串變量
bool flag = false; // 定義一個布爾類型變量
int age = 10; // 定義一個整數變量
複製代碼

建議:成員變量使用具體的類型,var只在局部變量中使用。代碼風格bash

5. 定義常量

支持使用final和const定義常量閉包

  • final 變量只能賦值一次
  • const 變量是編譯時常量(Const 變量同時也是 final 變量)
final name = 'Bob';
const bar = 1000000;
const atm = 1.01325 * bar;
複製代碼

6. const 其餘用法

建立不變的值異步

var foo = const []; // 定義一個不可變的集合
boo.add(1); // error
複製代碼

定義常量構造函數async

class A {
  const A();
}
A a1 = const A();
A a2 = const A();
print(a1 == a2); // true
複製代碼

7. 字符串

  • 可使用單引號或者雙引號來建立字符串
  • 在字符串中可使用${expression}表達式
  • 可使用三個單引號或者雙引號建立多行字符串
var s1 = 'Single quotes work well for string literals.';
var s2 = "Double quotes work just as well.";
var s3 = "expression $s2";
var s4 = "expression ${s2.toUpperCase()}";
var s5 = ''' You can create multi-line strings like this one. ''';
var s6 = """This is also a multi-line string.""";
複製代碼

8. 定義class

  • 全部的類都繼承於 Object
  • 不支持多繼承,但支持基於 mixin 的繼承機制,意味着每一個類(Object 除外) 都只有一個超類
  • 沒法像java同樣直接定義interface,但支持隱式接口,每一個類都隱式的定義了一個包含全部實例成員的接口, 而且這個類實現了這個接口
  • 使用abstract 修飾符定義一個抽象類,抽象類一般用來定義接口, 以及部分實現
// 定義class Person
class Person {
  // In the interface, but visible only in this library.
  final _name;
  // Not in the interface, since this is a constructor.
  Person(this._name);
  // In the interface.
  String greet(who) => 'Hello, $who. I am $_name.';
}
// 定義Imposter 實現Person隱式的interface
class Imposter implements Person {
  // 須要實現interface _name屬性
  final _name = "";
  // 須要實現interface greet方法
  String greet(who) => 'Hi $who. Do you know who I am?';
}
// 定義Imposter1 繼承Person類
class Imposter1 extends Person {
  Imposter1(name) : super(name);
}
複製代碼

定義抽象類ide

abstract class AbstractContainer {
  // 抽象方法不須要用abstract修飾符
  void updateChildren();
}
// 繼承抽象類
class SpecializedContainer extends AbstractContainer {
  // 實現抽象方法
  void updateChildren() {
    // ...Implement updateChildren()...
  }
}
// 實現抽象類AbstractContainer 隱式的interface
class SpecializedContainer1 implements AbstractContainer {
  // 實現interface的方法
  void updateChildren() {
    // ...Implement updateChildren()...
  }
}
複製代碼

9. mixin 繼承機制(爲類添加新的功能)

  • 定義mixin 跟定義class同樣,可是不能有構造函數,連無參的構造函數都不行;由於每一個Mixin都有一個自定義的構造函數被單獨調用,父類也是如此,所以Mixin的構造函數不可以被聲明,調用函數能夠省略
  • 使用 with 關鍵字 使用mixin
  • 使用mixin定義的class,是全部mixin類的子類
class A {
  void printA() {
    print("A");
  }
}
class B {
  void printB() {
    print("B");
  }
}
abstract class C {
  void printC();
}
// 第一種使用Mixin的方式
class D extends A with B, C {
  @override
  void printC() {
    print("C");
  }
  void printD() {
    print("D");
  }
}
// 第二種使用Mixin的方式
// 這種方法沒法定義class的實體
// 由於C 是有一個抽象方法,因此定義的E 須要abstract聲明
abstract class E = A with B, C;
class E1 extends E {
  @override
  void printC() {
    print("C");
  }
  void printE() {
    print("E");
  }
}
D d = new D();
d.printA(); // A
d.printB(); // B
d.printC(); // C
d.printD(); // D
print(d is C); // true
print(d is B); // true
print(d is A); // true
E1 e1 = new E1();
e1.printA(); // A
e1.printB(); // B
e1.printC(); // C
e1.printE(); // E
print(e1 is E); // true
print(e1 is C); // true
print(e1 is B); // true
print(e1 is A); // true
複製代碼

10. 構造函數

  • 默認構造函數,默認構造函數沒有參數
  • 支持命名構造函數;命名構造函數來更清晰的代表你的意圖
  • 支持常量構造函數;爲一個類提供一個狀態不變的對象, 且類的全部變量必需聲明爲 final類型
  • 支持工廠方法構造函數;使用factory 來定義 這個構造函數 構造函數執行順序:
  1. initializer list(初始化參數列表), 使用逗號分隔初始化表達式。
  2. superclass’s no-arg constructor(超類的無名構造函數)
  3. main class’s no-arg constructor(主類的無名構造函數)

命名構造函數

class Person {
  String firstName;
  
  // 命名構造函數
  Person.fromJson(Map data) {
    print('in Person');
  }
}
class Employee extends Person {
  // 必需調用父類的構造函數
  Employee.fromJson(Map data) : super.fromJson(data) {
    print('in Employee');
  }
}
class Point {
  num x;
  num y;
  Point(this.x, this.y);
  // 初始化 x、y 參數列表
  Point.fromJson(Map jsonMap)
      : x = jsonMap['x'],
        y = jsonMap['y'] {
    print('In Point.fromJson(): ($x, $y)');
  }
}
main() {
  var emp = new Employee.fromJson({});
}
複製代碼

常量構造函數

class ImmutablePoint {
  final num x;
  final num y;
  const ImmutablePoint(this.x, this.y);
  static final ImmutablePoint origin =
      const ImmutablePoint(0, 0);
}
複製代碼

工廠方法構造函數

class Logger {
  final String name;
  bool mute = false;
  // _cache is library-private, thanks to the _ in front
  // of its name.
  static final Map<String, Logger> _cache =
      <String, Logger>{};
  factory Logger(String name) {
    if (_cache.containsKey(name)) {
      return _cache[name];
    } else {
      final logger = new Logger._internal(name);
      _cache[name] = logger;
      return logger;
    }
  }
  Logger._internal(this.name);
  void log(String msg) {
    if (!mute) {
      print(msg);
    }
  }
}
var logger = new Logger('UI');
logger.log('Button clicked');
複製代碼

11. getters and setters方法

  • 沒有final修飾符的變量,隱含的具備 getter和setter方法
  • final修飾符的變量,隱含的具備 getter方法
class Rectangle {
  num left;
  num top;
  num width;
  num height;
  Rectangle(this.left, this.top, this.width, this.height);
  // Define two calculated properties: right and bottom.
  num get right             => left + width;
      set right(num value)  => left = value - width;
  num get bottom            => top + height;
      set bottom(num value) => top = value - height;
}
複製代碼

12. 流程控制語句(基本跟其餘語言同樣)

  • 支持if else
  • 支持標準的 for 循環
  • 對於實現了 Iterable 接口的類,支持 for-in 循環
  • 支持While and do-while 循環
  • 支持break和continue 終止和繼續下一次循環
  • 支持switce case語句;每一個非空的 case 語句都必須有一個 break 語句
// if else
if (isRaining()) {
  you.bringRainCoat();
} else if (isSnowing()) {
  you.wearJacket();
} else {
  car.putTopDown();
}
// for循環
var message = new StringBuffer("Dart is fun");
for (var i = 0; i < 5; i++) {
  message.write('!');
}
// for-in循環
var collection = [0, 1, 2];
for (var x in collection) {
  print(x);
}
// while 循環
while (!isDone()) {
  doSomething();
}
// do-while 循環
do {
  printLine();
} while (!atEndOfPage());
// switce case語句
var command = 'OPEN';
switch (command) {
  case 'CLOSED':
    executeClosed();
    break;
  case 'PENDING':
    executePending();
    break;
  default:
    executeUnknown();
}
複製代碼

13. 操做符(基本跟其餘語言同樣)

  • 支持 condition ? expr1 : expr2 表達式
  • 支持 expr1 ?? expr2; 若是 expr1 是 non-null,返回其值; 不然執行 expr2 並返回其結果
  • 支持?.操做符,避免空指針異常
  • 級聯操做符(..)
  • 支持位和移位操做符, &、|、^、~expr、<<、>>
  • 支持邏輯操做符,!expr、||、&&
// ?.操做符
var p = new Point(2, 2);
p?.y = 4;
// ?? 操做符
b ??= value; // 若是 b 是 null,則賦值給 b;
// 級聯操做符(..)
// 第一個方法 querySelector() 返回了一個 selector 對象。 後面的級聯操做符都是調用這個對象的成員, 並忽略每一個操做 所返回的值
querySelector('#button') // Get an object.
  ..text = 'Confirm'   // Use its members.
  ..classes.add('important')
  ..onClick.listen((e) => window.alert('Confirmed!'));
複製代碼

14. Lists(列表)

Dart 中數組就是 List 對象 簡單建立list

var list1 = [1, 2, 3];
assert(list.length == 3);
assert(list[1] == 2);
list[1] = 1;
assert(list[1] == 1);
複製代碼

使用構造函數建立list

var list2 = new List();
list2.add(1);
assert(list2[0] == 1);
複製代碼

15. Map

簡單建立 map

var gifts = {
// Keys      Values
  'first' : 'partridge',
  'second': 'turtledoves',
  'fifth' : 'golden rings'
};
複製代碼

使用 Map 構造函數建立Map

var gifts = new Map();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';
複製代碼

16. Functions(方法)

  • 全部的方法都是Function類型
  • 支持高階函數,能夠看成另外一個方法的參數
  • 若是方法以後一個表達式,可使用 => expr 語法, 這個 => expr 語法是 { return expr; } 形式的縮寫
  • 支持閉包,在方法內定義方法
  • 支持可選參數,包括可選命名參數和可選位置參數
  • 支持默認參數值
  • 全部的函數都返回一個值。若是沒有指定返回值,則 默認把語句 return null; 做爲函數的最後一個語句執行。
// 簡單的定義一個方法
bool isNoble(int atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}
// => expr表達式用法
// 注意: 在箭頭 (=>) 和冒號 (;) 之間只能使用一個 表達式 – 不能使用 語句。 例如:你不能使用 if statement,可是能夠 使用條件表達式
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
複製代碼

可選命名參數: 在定義方法的時候,使用 {param1, param2, …} 的形式來指定命名參數, 調用方法的時候,你可使用這種形式 paramName: value 來指定命名參數

// 定義
enableFlags({bool bold, bool hidden}) {
  // ...
}
// 定義帶有默認值的方法
void enableFlags1({bool bold = false, bool hidden = false}) {
  // ...
}
// 使用
enableFlags(bold: true, hidden: false);
複製代碼

可選位置參數:把一些方法的參數放到 [] 中就變成可選 位置參數了

String say(String from, String msg, [String device = 'carrier pigeon', String mood]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  if (mood != null) {
    result = '$result (in a $mood mood)';
  }
  return result;
}
// 不使用可選參數
say('Bob', 'Howdy'); // Bob says Howdy
// 使用可選參數
say('Bob', 'Howdy', 'smoke signal'); // Bob says Howdy with a smoke signal
複製代碼

17. Exceptions(異常)

  • Dart 提供了 Exception 和 Error 類型, 以及一些子類型
  • 與java不一樣,不能在定義方法的時候聲明異常, 即Dart 異常是非檢查型異常
  • 使用 throw 關鍵詞拋出異常, 支持拋出任意的對象
  • 使用 try cache finally捕獲異常,同時支持用 rethrow 從新拋出異常
try {
  // do something
} on Exception catch (e) {
  print(e);
  // 從新拋出這個異常
  rethrow;
} catch (e) {
  print(e);
  // 拋出任意的對象
  throw 'Out of llamas!';
} finally {
  print("finally");
}
複製代碼

18. 泛型

// 定義支持的泛型類
abstract class Cache<T> {
  T getByKey(String key);
  setByKey(String key, T value);
}
// 定義泛型函數
T first<T>(List<T> ts) {
  // ...Do some initial work or error checking, then...
  T tmp ?= ts[0];
  // ...Do some additional checking or processing...
  return tmp;
}
複製代碼

19. 枚舉類型

  • 沒法繼承枚舉類型、沒法使用 mix in、沒法實現一個枚舉類型
  • 沒法顯示的初始化一個枚舉類型
enum Color {
  red,
  green,
  blue
}
複製代碼

20. 異步支持

  • 支持 async await,(跟es6的async await差很少)
  • 使用 Future 或者 Stream執行異步操做
  • 支持在循環中使用異步
checkVersion() async {
  var version = await lookUpVersion();
  if (version == expectedVersion) {
    // Do something.
  } else {
    // Do something else.
  }
}
try {
  checkVersion();
} catch (e) {
  print(e);
}
// 在循環中使用異步
await for (var request in requestServer) {
  handleRequest(request);
}
複製代碼

21. Typedefs 給方法類型命名,保留類型信息

typedef int Compare(Object a, Object b);
class SortedCollection {
  Compare compare;
  SortedCollection(this.compare);
}
 // Initial, broken implementation.
 int sort(Object a, Object b) => 0;
main() {
  SortedCollection coll = new SortedCollection(sort);
  assert(coll.compare is Function);
  assert(coll.compare is Compare);
}
複製代碼

22. 註釋

  • 單行註釋以 //
  • 多行註釋以 /* 開始, */ 結尾
  • 文檔註釋可使用 /// 開始

23. 導包

使用 import 來指定一個庫如何使用另外 一個庫。

  • 對於內置的庫,URI 使用特殊的 dart: scheme
  • 對於其餘的庫,你可使用文件系統路徑或者 package: scheme
  • 若是兩個庫具備衝突的標識符,可使用庫的前綴來區分
  • 支持導入庫的一部分
  • 支持延遲載入庫
// 導入內置的庫
import 'dart:async';
import 'dart:io';
// 導入其餘的庫
import 'package:flutter/material.dart';
// 使用庫的前綴來解決衝突
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// Import only foo.
import 'package:lib1/lib1.dart' show foo;
// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;
// 延遲載入庫
import 'package:deferred/hello.dart' deferred as hello;
greet() async {
  await hello.loadLibrary();
  hello.printGreeting();
}
複製代碼
相關文章
相關標籤/搜索