flutter前言-dart語言(二)

通過dart語言(一)的學習,相信大家已經(jīng)可以很熟練的寫出完整的應用程序了玩敏,但是想要寫出更優(yōu)秀锤悄、更完美的dart語言框架,還需要更深入的理解dart語言的一些特點驼侠。
接下來,我將帶領大家一起更深入的學習dart語言谆吴。

目錄

image.png

泛型

使用<...> 的方式來定義泛型泪电。

為什么使用泛型?

  1. 雖然Dart 語言中類型是可選的纪铺,但是明確的指明使用的是泛型相速,會讓代碼更好理解。
 var names = new List<String>();
 names.addAll(['xiaojian', 'lili', 'jim']);
  1. 使用泛型讓代碼更簡潔
 abstract class IntCache {
   int getByKey(String key);
   setByKey(String key, int value);
 }
 abstract class StringCache {
   String getByKey(String key);
   setByKey(String key, String value);
 }
上面兩個類可以優(yōu)化為:
 abstract class Cache<T> {
   T getByKey(String key);
   setByKey(String key, T value);
 }

集合類型

泛型用于List 鲜锚、Set突诬、 Map 類型參數(shù)化

var names = <String>['Seth', 'Kathy', 'Lars'];
var pages = <String, String>{
  'index.html': 'Homepage',
  'robots.txt': 'Hints for web robots',
  'humans.txt': 'We are people, not machines'
};

構造函數(shù)中參數(shù)化類型
var names = new List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
var nameSet = new Set<String>.from(names);
var views = new Map<int, View>();

泛型集合及它們所包含的類型
var names = new List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
print(names is List<String>); // true

庫和可見性

使用import 和 library 指令可以方便的創(chuàng)建一個模塊或分享代碼。一個Dart 庫不僅能夠提供相應的API芜繁,還可以包含一些以_開頭的私有變量僅在庫內部可見旺隙。
每一個Dart 應用都是一個庫,即使它沒有使用library指令骏令。庫可以方便是使用各種類型的包蔬捷。

使用庫

使用import指定怎樣的命名空間,從一個庫引用另一個庫。
import唯一要求的參數(shù)是指定庫的URI周拐。

  • dart內置庫铡俐,URI組合dart:
  • 其他庫,使用文件路徑或package:組合妥粟,package:組合式通過包管理工具提供的审丘。
import 'package:flutter/material.dart';
import 'Home.dart';

庫的前綴

如果導入的庫擁有相互沖突的名字,使用as為其中一個或幾個指定不一樣的前綴勾给。

import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;

Element element1 = new Element();           // Uses Element from lib1.
lib2.Element element2 = new lib2.Element(); // Uses Element from lib2.

導入庫的一部分

如果只需要使用庫的一部分內容滩报,使用show或hide有選擇的導入。

// 僅導入foo.
import 'package:lib1/lib1.dart' show foo;
// 除了foo都導入
import 'package:lib2/lib2.dart' hide foo;

延遲加載

延遲加載播急,也叫懶加載脓钾,允許應用程序按需加載庫。使用延遲加載的場景:

  • 減少程序初始化啟動時間桩警。
  • 執(zhí)行A/B測試——嘗試替換一個算法的實現(xiàn)可训。
  • 加載很少用的功能,比如可選的屏幕和對話框生真。
    要延遲加載一個庫沉噩,首先必須使用deferred as導入它捺宗,當需要使用庫的時候柱蟀,使用庫名調用loadLibrary()。
import 'package:deferred/hello.dart' deferred as hello;
greet() async {
  // 使用await關鍵字暫停執(zhí)行蚜厉,直到庫加載
  await hello.loadLibrary();
  hello.printGreeting();
}

異步(async和await)

使用async函數(shù)和await表達式實現(xiàn)異步操作长已。

當需要使用一個從Future返回的值時,有兩個選擇:

  • 使用async和await昼牛。
  • 使用Future API术瓮。

當需要從一個Stream獲取值時,有兩個選擇:

  • 使用async和異步的循環(huán)(await for)贰健。
  • 使用Stream API胞四。

代碼使用了async和await就是異步的,雖然看起來像同步代碼伶椿。

  static postData(String path, Map<String, String> params,Function successCallBack) async {
    var httpClient = HttpClient();
    var uri = new Uri.https(
        HOST, path, _createPostData(params));
    var request = await httpClient.postUrl(uri);
    var response = await request.close();
    if (response.statusCode == HttpStatus.OK) {
      var json = await response.transform(UTF8.decoder).join();
      var data = JSON.decode(json);

      print("data=====" + data.toString() );
      if(successCallBack!=null){
        successCallBack(data['data']);
      }

    } else {
      print("data=====error");
    }
  }

聲明異步函數(shù)

異步函數(shù)是一個被async標記的函數(shù)辜伟。
雖然異步的函數(shù)中可能執(zhí)行耗時的操作,但是函數(shù)本身在調用后將會立即返回脊另,即使函數(shù)體一條語句也沒執(zhí)行导狡。
給函數(shù)添加async關鍵字將使函數(shù)返回一個Future類型

checkVersion() async {
  // ...
}
lookUpVersion() async => /* ... */;

案例

   getData(String path, Map<String, String> params) async {
    var httpClient = HttpClient();
    var uri = new Uri.https(
        HOST, path, _createPostData(params));
    var request = await httpClient.postUrl(uri);
    var response = await request.close();
    return await response.transform(UTF8.decoder).join();
  }

調用函數(shù)想獲得其結果:

void main(){
  String a =  getData("/bbs/list",map);
  print(a);
}

運行后程序報錯:

Failed to load "/Users/wangxiaojian/Documents/androidCode/flutter_rong_app/test/widget_test.dart": type 'Future<dynamic>' is not a subtype of type 'String'

test/widget_test.dart 55:14                                                                    main
===== asynchronous gap ===========================
package:test                                                                                   serializeSuite
/var/folders/j7/0w0w7vgd6s5f_gv67_jfzgjr0000gn/T/dart_test_listenerqkAJjf/listener.dart 19:27  main

因為data是String類型,而函數(shù)getData()是一個異步操作函數(shù)偎痛,其返回值是一個await延遲執(zhí)行的結果旱捧。在Dart中,有await標記的運算踩麦,其結果值都是一個Future對象枚赡,F(xiàn)uture不是String類型氓癌,所以就報錯了。

那如果這樣的話标锄,我們就沒法獲取到延遲執(zhí)行的結果了顽铸?當然可以,Dart規(guī)定有async標記的函數(shù)料皇,只能由await來調用谓松,比如這樣:

void main() async{
 // await 必須在有async標記的函數(shù)中運行
  String a = await getData("/bbs/list",map);
  print(a);
}

上面這種方法一般用于調用封裝好的異步接口,比如getData()被封裝到了其他dart文件践剂,通過使用async函數(shù)對其調取使用

  • await關鍵字必須在async函數(shù)內部使用
  • 調用async函數(shù)必須使用await關鍵字

PS:await關鍵字真的很形象鬼譬,等一等的意思,就是說逊脯,既然你運行的時候都要等一等优质,那我調用的時候也等一等吧

為什么要用Future?

在定義Flutter函數(shù)時军洼,還可以指定其運行結果返回值的類型巩螃,以提高代碼的可讀性:

Future<String> getData(String path, Map<String, String> params) async {
    var httpClient = HttpClient();
    var uri = new Uri.https(
        HOST, path, _createPostData(params));
    var request = await httpClient.postUrl(uri);
    var response = await request.close();
    return await response.transform(UTF8.decoder).join();
 }

Future最主要的功能就是提供了鏈式調用,熟悉ES6語法的小伙伴都應該很熟悉匕争,鏈式調用解決兩大問題:明確代碼執(zhí)行的依賴關系和實現(xiàn)異常捕獲避乏。
看下面案例:

String _name = "";

void _setName(String name) async{
  _name =  name;
}

void _getName() async{
   await _setName("wangxiaojian");
   print(_name);
}

void main() async{
   await _getName();
}

如果要想先執(zhí)行_getName再執(zhí)行_setName,必須在_getName中await _setName();_setName的代碼與_getName耦合甘桑,將來如果_getName廢掉或者改動拍皮,_setName中還需要經(jīng)過修改以適配變更。

為了解決此問題跑杭,F(xiàn)uture提供了一套非常簡潔的解決方案,而async和await無法企及的铆帽,因此掌握Future還是很有必要滴:

String _name = "";
_setName() {
  _name = "wangxiaojian";
}
_getName() {
  print(_name);
}
void main() {
  new Future(_setName()).then(_getName());
}

可調用類

Dart 語言中為了能夠讓類像函數(shù)一樣能夠被調用,可以實現(xiàn)call()方法德谅。

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

main() {
  var cf = new ClassFunction();
  var out = cf("wangxiaojian","is","talent");
  print('$out');
  print(cf.runtimeType);
  print(out.runtimeType);
  print(cf is Function);
}
運行結果:
wangxiaojian is talent!
ClassFunction
String
false

類型定義

typedef關鍵字爹橱,用來聲明一種類型,當一個函數(shù)類型分配給一個變量時窄做,保留類型信息愧驱。

// 聲明一種 Compare類型
typedef int Compare(int a, int b);

int sort(int a, int b) => a - b;

main() {
  print(sort is Compare); 
}
運行結果:
true

元數(shù)據(jù)

元數(shù)據(jù)是以@開始的修飾符。在@ 后面接著編譯時的常量或調用一個常量構造函數(shù)浸策。

所有dart代碼中可用的三個注解:

  • @deprecated 被棄用的
  • @override 重載
  • @proxy 代理

定義自己的元數(shù)據(jù)

通過library來定義一個庫冯键,在庫中定義一個相同名字的class,然后在類中定義const 構造方法庸汗。

// 定義
library todo;

class todo {
  final String who;
  final String what;

  const todo(this.who, this.what);
}

// 使用
import 'todo.dart';

@todo('seth', 'make this do something')
void doSomething() {
  print('do something');
}

元數(shù)據(jù)可以修飾library(庫), class(類), typedef(類型定義), type parameter(類型參數(shù)), constructor(構造函數(shù)), factory(工廠函數(shù)), function(函數(shù)), field(作用域), parameter(參數(shù)), 或者 variable declaration(變量聲明)惫确。

可以使用reflection反射,在運行時檢查元數(shù)據(jù)。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末改化,一起剝皮案震驚了整個濱河市掩蛤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌陈肛,老刑警劉巖揍鸟,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異句旱,居然都是意外死亡阳藻,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門谈撒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來腥泥,“玉大人,你說我怎么就攤上這事啃匿』淄猓” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵溯乒,是天一觀的道長夹厌。 經(jīng)常有香客問我,道長裆悄,這世上最難降的妖魔是什么矛纹? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮灯帮,結果婚禮上崖技,老公的妹妹穿的比我還像新娘逻住。我一直安慰自己钟哥,他們只是感情好,可當我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布瞎访。 她就那樣靜靜地躺著腻贰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪扒秸。 梳的紋絲不亂的頭發(fā)上播演,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天,我揣著相機與錄音伴奥,去河邊找鬼写烤。 笑死,一個胖子當著我的面吹牛拾徙,可吹牛的內容都是我干的洲炊。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼暂衡!你這毒婦竟也來了询微?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤狂巢,失蹤者是張志新(化名)和其女友劉穎撑毛,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體唧领,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡藻雌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了斩个。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蹦疑。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖萨驶,靈堂內的尸體忽然破棺而出歉摧,到底是詐尸還是另有隱情,我是刑警寧澤腔呜,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布叁温,位于F島的核電站,受9級特大地震影響核畴,放射性物質發(fā)生泄漏膝但。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一谤草、第九天 我趴在偏房一處隱蔽的房頂上張望跟束。 院中可真熱鬧,春花似錦丑孩、人聲如沸冀宴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽略贮。三九已至,卻和暖如春仗岖,著一層夾襖步出監(jiān)牢的瞬間逃延,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工轧拄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留揽祥,地道東北人。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓檩电,卻偏偏與公主長得像拄丰,于是被迫代替她去往敵國和親桅打。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內容