[Flutter] 一些面試可能會問基礎知識
1. Flutter 是什麼?
Flutter是谷歌的移動UI框架,可以快速在iOS和Android上構建高質量的原生使用者介面。Flutter可以與現有的程式碼一起工作。在全世界,Flutter正在被越來越多的開發者和組織使用,並且Flutter是完全免費、開源的。
2. Flutter 特性有哪些?
快速開發(毫秒級熱過載)
- 絢麗UI(內建漂亮的質感設計Material Design和Cupertino Widget和豐富平滑的動畫效果和平臺感知)
- 響應式(Reactive,用強大而靈活的API解決2D、動畫、手勢、效果等難題)
- 原生訪問功能
- 堪比原生效能
3. Flutter 和 Dart的關係是什麼?
Flutter是一個使用Dart語言開發的跨平臺移動UI框架,通過自建繪製引擎,能高效能、高保真地進行移動開發。Dart囊括了多數程式語言的優點,它更符合Flutter構建介面的方式。
4.Dart 語言的特性?
- Productive(生產力高,Dart的語法清晰明瞭,工具簡單但功能強大)
- Fast(執行速度快,Dart提供提前優化編譯,以在移動裝置和Web上獲得可預測的高效能和快速啟動。)
- Portable(易於移植,Dart可編譯成ARM和X86程式碼,這樣Dart移動應用程式可以在iOS、Android和其他地方執行)
- Approachable(容易上手,充分吸收了高階語言特性,如果你已經知道C++,C語言,或者Java,你可以在短短几天內用Dart來開發)
- Reactive(響應式程式設計)
5.Dart的一些重要概念?
- 在Dart中,一切都是物件,所有的物件都是繼承自Object
- Dart是強型別語言,但可以用var或 dynamic來宣告一個變數,Dart會自動推斷其資料型別,dynamic類似c#
- 沒有賦初值的變數都會有預設值null
- Dart支援頂層方法,如main方法,可以在方法內部建立方法
- Dart支援頂層變數,也支援類變數或物件變數
- Dart沒有public protected private等關鍵字,如果某個變數以下劃線(_)開頭,代表這個變數在庫中是私有的
6.dart是值傳遞還是引用傳遞?
dart中,基本資料型別傳值,類傳引用。
7.Widget 和 element 和 RenderObject 之間的關係?
- Widget是使用者介面的一部分,並且是不可變的。
- Element是在樹中特定位置Widget的例項。
- RenderObject是渲染樹中的一個物件,它的層次結構是渲染庫的核心。
Widget會被inflate(填充)到Element,並由Element管理底層渲染樹。Widget並不會直接管理狀態及渲染,而是通過State這個物件來管理狀態。Flutter建立Element的可見樹,相對於Widget來說,是可變的,通常介面開發中,我們不用直接操作Element,而是由框架層實現內部邏輯。就如一個UI檢視樹中,可能包含有多個TextWidget(Widget被使用多次),但是放在內部檢視樹的視角,這些TextWidget都是填充到一個個獨立的Element中。Element會持有renderObject和widget的例項。記住,Widget 只是一個配置,RenderObject 負責管理佈局、繪製等操作。
在第一次建立 Widget 的時候,會對應建立一個 Element, 然後將該元素插入樹中。如果之後 Widget 發生了變化,則將其與舊的 Widget 進行比較,並且相應地更新 Element。重要的是,Element 不會被重建,只是更新而已。
8.mixin extends implement 之間的關係?
繼承(關鍵字 extends)、混入 mixins (關鍵字 with)、介面實現(關鍵字 implements)。這三者可以同時存在,前後順序是extends -> mixins -> implements。
Flutter中的繼承是單繼承,子類重寫超類的方法要用@Override,子類呼叫超類的方法要用super。
在Flutter中,Mixins是一種在多個類層次結構中複用類程式碼的方法。mixins的物件是類,mixins絕不是繼承,也不是介面,而是一種全新的特性,可以mixins多個類,mixins的使用需要滿足一定條件。
9.使用mixins的條件是什麼?
因為mixins使用的條件,隨著Dart版本一直在變,這裡講的是Dart2.1中使用mixins的條件:
mixins類只能繼承自object
mixins類不能有建構函式
一個類可以mixins多個mixins類
可以mixins多個類,不破壞Flutter的單繼承
10. mixin 怎麼指定異常型別?
on關鍵字可用於指定異常型別。 on只能用於被mixins標記的類,例如mixins X on A,意思是要mixins X的話,得先介面實現或者繼承A。這裡A可以是類,也可以是介面,但是在mixins的時候用法有區別.
on 一個類:
class A { void a(){ print("a"); } } mixin X on A{ void x(){ print("x"); } } class mixinsX extends A with X{ }
on 的是一個介面: 得首先實現這個介面,然後再用mix
class A { void a(){ print("a"); } } mixin X on A{ void x(){ print("x"); } } class implA implements A{ @override void a() {} } class mixinsX2 extends implA with X{ }
11.Flutter main future mirotask 的執行順序?
普通程式碼都是同步執行的,結束後會開始檢查microtask中是否有任務,若有則執行,執行完繼續檢查microtask,直到microtask列隊為空。最後會去執行event佇列(future)。
12.Future和Isolate有什麼區別?
future是非同步程式設計,呼叫本身立即返回,並在稍後的某個時候執行完成時再獲得返回結果。在普通程式碼中可以使用await 等待一個非同步呼叫結束。
isolate是併發程式設計,Dartm有併發時的共享狀態,所有Dart程式碼都在isolate中執行,包括最初的main()。每個isolate都有它自己的堆記憶體,意味著其中所有記憶體資料,包括全域性資料,都僅對該isolate可見,它們之間的通訊只能通過傳遞訊息的機制完成,訊息則通過埠(port)收發。isolate只是一個概念,具體取決於如何實現,比如在Dart VM中一個isolate可能會是一個執行緒,在Web中可能會是一個Web Worker。
13.Stream 與 Future是什麼關係?
Stream 和 Future 是 Dart 非同步處理的核心 API。Future 表示稍後獲得的一個數據,所有非同步的操作的返回值都用 Future 來表示。但是 Future 只能表示一次非同步獲得的資料。而 Stream 表示多次非同步獲得的資料。比如介面上的按鈕可能會被使用者點選多次,所以按鈕上的點選事件(onClick)就是一個 Stream 。簡單地說,Future將返回一個值,而Stream將返回多次值。Dart 中統一使用 Stream 處理非同步事件流。Stream 和一般的集合類似,都是一組資料,只不過一個是非同步推送,一個是同步拉取。
14.Stream 兩種訂閱模式?
Stream有兩種訂閱模式:單訂閱(single)和多訂閱(broadcast)。單訂閱就是隻能有一個訂閱者,而廣播是可以有多個訂閱者。這就有點類似於訊息服務(Message Service)的處理模式。單訂閱類似於點對點,在訂閱者出現之前會持有資料,在訂閱者出現之後就才轉交給它。而廣播類似於釋出訂閱模式,可以同時有多個訂閱者,當有資料時就會傳遞給所有的訂閱者,而不管當前是否已有訂閱者存在。
Stream 預設處於單訂閱模式,所以同一個 stream 上的 listen 和其它大多數方法只能呼叫一次,呼叫第二次就會報錯。但 Stream 可以通過 transform() 方法(返回另一個 Stream)進行連續呼叫。通過 Stream.asBroadcastStream() 可以將一個單訂閱模式的 Stream 轉換成一個多訂閱模式的 Stream,isBroadcast 屬性可以判斷當前 Stream 所處的模式。
15.await for 如何使用?
await for是不斷獲取stream流中的資料,然後執行迴圈體中的操作。它一般用在直到stream什麼時候完成,並且必須等待傳遞完成之後才能使用,不然就會一直阻塞。
Stream<String> stream = new Stream<String>.fromIterable(['不開心', '面試', '沒', '過']); main() async{ print('上午被開水燙了腳'); await for(String s in stream){ print(s); } print('晚上還沒吃飯'); }
16. Flutter中的Widget、State、Context 的核心概念?是為了解決什麼問題?
Widget: 在Flutter中,幾乎所有東西都是Widget。將一個Widget想象為一個視覺化的元件(或與應用視覺化方面互動的元件),當你需要構建與佈局直接或間接相關的任何內容時,你正在使用Widget。
Widget樹: Widget以樹結構進行組織。包含其他Widget的widget被稱為父Widget(或widget容器)。包含在父widget中的widget被稱為子Widget。
Context: 僅僅是已建立的所有Widget樹結構中的某個Widget的位置引用。簡而言之,將context作為widget樹的一部分,其中context所對應的widget被新增到此樹中。一個context只從屬於一個widget,它和widget一樣是連結在一起的,並且會形成一個context樹。
State: 定義了StatefulWidget例項的行為,它包含了用於”互動/干預“Widget資訊的行為和佈局。應用於State的任何更改都會強制重建Widget。
這些狀態的引入,主要是為了解決多個部件之間的互動和部件自身狀態的維護。
17. Widget的兩種型別是什麼?
StatelessWidget: 一旦建立就不關心任何變化,在下次構建之前都不會改變。它們除了依賴於自身的配置資訊(在父節點構建時提供)外不再依賴於任何其他資訊。比如典型的Text、Row、Column、Container等,都是StatelessWidget。它的生命週期相當簡單:初始化、通過build()渲染。
StatefulWidget: 在生命週期內,該類Widget所持有的資料可能會發生變化,這樣的資料被稱為State,這些擁有動態內部資料的Widget被稱為StatefulWidget。比如複選框、Button等。State會與Context相關聯,並且此關聯是永久性的,State物件將永遠不會改變其Context,即使可以在樹結構周圍移動,也仍將與該context相關聯。當state與context關聯時,state被視為已掛載。StatefulWidget由兩部分組成,在初始化時必須要在createState()時初始化一個與之相關的State物件。
18. State 物件的初始化流程?
initState() : 一旦State物件被建立,initState方法是第一個(建構函式之後)被呼叫的方法。可通過重寫來執行額外的初始化,如初始化動畫、控制器等。重寫該方法時,應該首先呼叫super.initState()。在initState中,無法真正使用context,因為框架還沒有完全將其與state關聯。initState在該State物件的生命週期內將不會再次呼叫。
didChangeDependencies(): 這是第二個被呼叫的方法。在這一階段,context已經可用。如果你的Widget連結到了一個InheritedWidget並且/或者你需要初始化一些listeners(基於context),通常會重寫該方法。
build(BuildContext context): 此方法在didChangeDependencies()、didUpdateWidget()之後被呼叫。每次State物件更新(或當InheritedWidget有新的通知時)都會呼叫該方法!我們一般都在build中來編寫真正的功能程式碼。為了強制重建,可以在需要的時候呼叫setState((){...})方法。
dispose(): 此方法在Widget被廢棄時呼叫。可重寫該方法來執行一些清理操作(如解除listeners),並在此之後立即呼叫super.dispose()。
19. Widget 唯一標識Key有那幾種?
在flutter中,每個widget都是被唯一標識的。這個唯一標識在build或rendering階段由框架定義。該標識對應於可選的Key引數,如果省略,Flutter將會自動生成一個。
在flutter中,主要有4種類型的Key:GlobalKey(確保生成的Key在整個應用中唯一,是很昂貴的,允許element在樹周圍移動或變更父節點而不會丟失狀態)、LocalKey、UniqueKey、ObjectKey。
20. 什麼是Navigator? MaterialApp做了什麼?
Navigator是在Flutter中負責管理維護頁面堆疊的導航器。MaterialApp在需要的時候,會自動為我們建立Navigator。Navigator.of(context),會使用context來向上遍歷Element樹,找到MaterialApp提供的_NavigatorState再呼叫其push/pop方法完成導航操作。