說實話,第一個、第三個、第六個我準備的話應該能答出來的,可是一個多月沒碰Flutter了,忘了都差很少。。。 等下把二面的答案寫出來,但願能幫助後來人。 此外GitHub和博客維護好很重要,像我這種demo隨手寫,隨手刪的人直接GG。。java
首先給個結論,dart是值傳遞。面試
以前把引用傳遞理解錯了,給各位讀者報個歉,同時也感謝評論區的指正express
先來看段代碼編程
main(){
Test a = new Test(5);
print("a的初始值爲:${a.value}");
setValue(a);
print("修改後a的值爲: ${a.value}");
}
class Test{
int value = 1;
Test(int newValue){
this.value = newValue;
}
}
setValue(Test s){
print("修改value爲100");
s.value = 100;
}
複製代碼
輸出結果爲:api
a的初始值爲:5
修改value爲100
修改後a的值爲:100
複製代碼
從這裏能夠看出是值傳遞,若是隻是複製了一個對象的話,main
函數中的a
值是不會發生變化的。 有些人可能會以如下代碼反駁我:bash
main(){
int s = 6;
setValue(s);
print(s); //輸出6,而不是7
}
class Test{
int value = 1;
Test(int newValue){
this.value = newValue;
}
}
setValue(int s){
s += 1;
}
複製代碼
你看,這輸出的不是6嗎,在dart
中一切皆爲對象,若是是值傳遞,那爲何是6啊。app
答案是這樣的,在setValue()
方法中,參數s
實際上和咱們初始化int s = 6
的s
不是一個對象,只是他們如今指的是同一塊內存區域,而後在setValue()
中調用s += 1
的時候,這塊內存區域的對象執行+1
操做,而後在堆(類比java)中產生了一個新的對象,s
再指向這個對象。因此s
參數只是把main
函數中的s
的內存地址複製過去了,就好比java中的:jvm
public class Test {
public static void main(String[] args) {
//至關於dart中main函數初始化
Test a = new Test();
//至關於setValue()中的s,並把參數表明的內存地址賦值給b
Test b = a;
//s指向一個新對象,即爲dart中的s += 1
b = new Test();
}
}
複製代碼
咱們只要記住一點,參數是把內存地址傳過去了,若是對這個內存地址上的對象修改,那麼其餘位置的引用該內存地址的變量值也會修改。千萬要記住dart中一切都是對象。async
偷偷說一句,我以爲面試官這個地方面試的很差,這種細節問題,若是不是遇到什麼bug,業務忙的時候是沒時間注意這個的,面試官能夠把這兩種狀況展現下,而後問面試者緣由是什麼。。而後我就能回答出來了。。哭唧唧。。ide
首先我詳細說下當時的情景,面試官問我Widget
和Element
之間是否是一對多的關係,若是是增長一個Widget
以後,這個關係又是什麼。 這部分仍是沒有很好地答案,如今只是一個猜測,若是添加了一個widget
,Element
樹遍歷後面全部的Element
看類型是否發生改變,有的話再重建RenderObject
。Element
和Widget
之間應該仍是一對一的關係,由於每一個Widget
的context
都是獨一無二的。等想好了再寫上去吧。
仍是沒能理解面試官的意思。。有可以理解的同窗請評論告知我一下。 如今理解了,面試官的意思應該指是runApp()方法中的那個的Widget。我當時也想說的,不過忘記這個方法名是啥了。。。
這部分能夠參考掘金的小德大佬的文章,高產似那啥。。
一樣參考小德的文章
級聯符號 .. 可讓你連續操做相同的對象,不單能夠連續地調用函數,還能夠連續地訪問方法,這樣作能夠避免建立臨時變量,從而寫出更流暢的代碼,流式編程更符合現代編程習慣和編程風格:
main(){
Tree tree = new Tree(1);
tree..test1 = 1..test2 =5;
print(tree.test1);
print(tree.test2);
}
class Tree{
int value;
int test1 = 2;
int test2 = 3;
Tree(int a){
this.value = a;
}
}
複製代碼
先來一段官方文檔
await-for
As every Dart programmer knows, the for-in loop plays well with iterables. Similarly, the await-for loop is designed to play well with streams. Given a stream, one can loop over its values: Every time an element is added to the stream, the loop body is run. After each iteration, the function enclosing the loop suspends until the next element is available or the stream is done. Just like await expressions, await-for loops can only appear inside asynchronous functions.
大概意思就是await for
是不斷獲取stream
流中的數據,而後執行循環體中的操做。
Stream<String> stream = new Stream<String>.fromIterable(['不開心', '面試', '沒', '過']);
main() async{
print('上午被開水燙了腳');
await for(String s in stream){
print(s);
}
print('晚上還沒吃飯');
}
複製代碼
輸出爲
上午被開水燙了腳
不開心
面試
沒
過
晚上還沒吃飯
複製代碼
await for
和 listen
的做用很類似,都是獲取流中數據而後輸出,可是正如await for
中的await
所示,若是stream
沒有傳遞完成,就會一直阻塞在這個位置,上面沒吃飯是最後輸出的,下面給個listen
的實例,一看就懂。
Stream<String> stream = new Stream<String>.fromIterable(['不開心', '面試', '沒', '過']);
main(){
print('上午被開水燙了腳');
stream.listen((s) { print(s); });
print('晚上還沒吃飯');
}
複製代碼
輸出爲
上午被開水燙了腳
晚上還沒吃飯
不開心
面試
沒
過
複製代碼
因此await for
通常用在直到stream
何時完成,而且必須等待傳遞完成以後才能使用,否則就會一直阻塞,形成相似於Android ANR
的問題。
其實面試官仍是很nice的,第一次見到活的大佬。。大佬對flutter和dart的研究真的很深刻,遠不是我這種只會調api的人能夠比擬的。 主要仍是我一個半月沒使用過flutter了,而後以前問其餘大佬要不要準備Flutter,大佬們說不用,之前看的不少東西都忘的差很少了。 哎,仍是本身準備不充分,或者開始大佬問個人時候直接回答忘得差很少了,應該就能過了吧。
另:求Android實習一份,最好是大廠的。。。