能够算是Flutter面试凉凉经吧

一面问的Java 和Android基础

  1. Jvm虚拟机
  2. messageQueue会不会阻塞ui线程
  3. 对象锁和类锁
  4. 之字形打印树
  5. 还有其余的记不清了,主要是我对二面印象太深入了。

二面问的Flutter和Dart

  1. dart是值传递仍是引用传递
  2. Widget和element和RenderObject之间的关系
  3. widget的root节点
  4. mixin extends implement之间的关系(除了extends其余的没怎么用过。。)
  5. jvm内存模型(感受这个是面试官可怜我,看我什么都不会才问的=。=)
  6. Future和microtask执行顺序
  7. dart中..的用法(基本没用过。。)
  8. await for(没用过。。)

说实话,第一个、第三个、第六个我准备的话应该能答出来的,可是一个多月没碰Flutter了,忘了都差很少。。。 等下把二面的答案写出来,但愿能帮助后来人。 此外GitHub和博客维护好很重要,像我这种demo随手写,随手删的人直接GG。。java

1. dart是值传递仍是引用传递

首先给个结论,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 = 6s不是一个对象,只是他们如今指的是同一块内存区域,而后在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

2. Widget和element和RenderObject之间的关系

首先我详细说下当时的情景,面试官问我WidgetElement之间是否是一对多的关系,若是是增长一个Widget以后,这个关系又是什么。 这部分仍是没有很好地答案,如今只是一个猜测,若是添加了一个widgetElement树遍历后面全部的Element看类型是否发生改变,有的话再重建RenderObjectElementWidget之间应该仍是一对一的关系,由于每一个Widgetcontext都是独一无二的。等想好了再写上去吧。

3. widget树的root节点

仍是没能理解面试官的意思。。有可以理解的同窗请评论告知我一下。 如今理解了,面试官的意思应该指是runApp()方法中的那个的Widget。我当时也想说的,不过忘记这个方法名是啥了。。。

4. mixin extends implement之间的关系

这部分能够参考掘金的小德大佬的文章,高产似那啥。。

6. Future和microtask执行顺序

一样参考小德的文章

7. dart中..是什么

级联符号 .. 可让你连续操做相同的对象,不单能够连续地调用函数,还能够连续地访问方法,这样作能够避免建立临时变量,从而写出更流畅的代码,流式编程更符合现代编程习惯和编程风格:

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;
  }
}
复制代码

8. await for使用

先来一段官方文档

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 forlisten的做用很类似,都是获取流中数据而后输出,可是正如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实习一份,最好是大厂的。。。

相关文章
相关标签/搜索