如下圖所示,通過提取編譯后的代碼,「可以看到 playerAnimation 其實被轉變成了 Animation? 的可空對象」,而當 playerAnimation 被調用時,通過 get playerAnimation() 進行判斷,如果此時 playerAnimation == null , 直接就拋出 LateError 錯誤。

「所以當我們訪問 late 聲明的對象時,如果對象還沒有初始化,就會返回一個異常。」

[]( )typedef

===================================================================

介紹完 late 接下介紹下 typedef, typedef 在 Dart 2.13 開始可以用于**「新的類型別名功能」**,比如:

// Type alias for functions (existing)

typedef ValueChanged = void Function(T value);

// Type alias for classes (new!)

typedef StringList = List;

// Rename classes in a non-breaking way (new!)

@Deprecated("Use NewClassName instead")

typedef OldClassName = NewClassName;

那么 typedef 是如何工作的?如下圖所示,可以看到 _getDeviceInfo 方法在編譯后,其實直接就被替換為 List ,所以**「實際上 StringList 是不參與到編譯后的代碼運行」**,所以也不會對代碼的運行效率有什么影響。

再舉個例子,如下圖所示,可以看到通過 SelectItemChanged 聲明的 selectItemChanged,在編譯后其實直接就是 final field (dynamic) →? void selectItemChanged; 。

接著我們通過 Dart 的 tear-off 來看另外一個現象,如下圖所示,可以看到我們從一個任意對象中 x中提取了 toString方法,通過閉包,就可以像調用常規實例一樣調用 x。

?

如果在一個對象上調用函數并省略了括號, Dart 稱之為 ”tear-off” :一個和函數使用同樣參數的閉包,當調用閉包的時候會執行其中的函數,比如:names.forEach(print); 等同于 names.forEach((name){print(name);});

?

那么編譯后的 getToString 方法會是怎么樣的?

如下圖所示,可以看到 getToString 方法在編譯后成了一個 static 的靜態方法,并且 ToStringFn 也沒有實際參與運行,也是被替換成了對應的 ()-> core:String 。

「所以對于編譯后的代碼,typedef 并不會對性能和運行結果產生影響。」

[]( )extension

=====================================================================

在 Dart 里,通過 extension 可以很便捷地為對象進行拓展,「那 extension 關鍵字是如何在原對象基礎上實現拓展呢?」

如下圖所示,我們聲明了一個 Cat 的枚舉,并且對 Cat 進行了拓展,從而為枚舉的每個值賦值,并且加了 talk 方法。

如下圖所示,「編譯后 Cat 里的枚舉值對應變成了一個 static final 的固定地址」,并且 CatExtension 里的 talk 和 value 也被指向了新的位置。

找到對應的實現處發現,「CatExtension 里的 name 和 talk 都變了所在文件下的 static method」 ,并且 talk 方法是先定義了 method 實現,之后再通過 tearoff 的 get 實現去調用,「基本上所有在 extension 里定義的方法都會有對應的 method 和 tearoff。」

如下圖所示,在 Cat 的使用處,編譯后可以看到 cat.talk() 其實就是執行了 main::CatExtension|talk 。

[]( )async / await

=========================================================================

最后聊聊 async / await ,我們都知道這是 Dart 里 Future 的語法糖,那這個語法糖在編譯后是如何運行的呢?

可以看到,loadmore 方法在編譯后被添加了很多的代碼,其中定義了一個 _Future async_future 并在最后返回,同時我們需要執行的代碼被包裝到 async_op 里去執行,而這里有一個很關鍵的地方就是,「async_op 對執行的內容進行了 try catch 的操作,并通過 _completeOnAsyncError 返回」

「這也是為什么我們在外部對一個 Future 進行 try catch 不能捕獲異常的原因」,所以如下圖所示,對于 Future 需要通過 .onError((error, stackTrace) => null) 的方式來對異常進行捕獲處理。

明白了這些關鍵字背后的實現后,相信可以更好地幫助你在 Flutter 的日常開發中更優雅地組織你的代碼,從而避免很多不必要的問題。

「當然,如果用不上,拿去面試“裝X”其實也挺不錯的不是么?」

結語

  • 現在隨著短視頻,抖音,快手的流行NDK模塊開發也顯得越發重要,需要這塊人才的企業也越來越多,隨之學習這塊的人也變多了,音視頻的開發,往往是比較難的,而這個比較難的技術就是NDK里面的技術。
  • 音視頻/高清大圖片/人工智能/直播/抖音等等這年與用戶最緊密,與我們生活最相關的技術一直都在尋找最終的技術落地平臺,以前是windows系統,而現在則是移動系統了,移動系統中又是以Android占比絕大部分為前提,所以AndroidNDK技術已經是我們必備技能了。
  • 要學習好NDK,其中的關于C/C++,jni,Linux基礎都是需要學習的,除此之外,音視頻的編解碼技術,流媒體協議,ffmpeg這些都是音視頻開發必備技能,而且
  • OpenCV/OpenGl/這些又是圖像處理必備知識,下面這些我都是當年自己搜集的資料和做的一些圖,因為當年我就感覺視頻這塊會是一個大的趨勢。所以提前做了一些準備。現在拿出來分享給大家。

本文已被[CODING開源項目:《Android學習筆記總結+移動架構視頻+大廠面試真題+項目實戰源碼》]( )收錄