Code Monkey home page Code Monkey logo

flutter_interview's Introduction

flutter_interview

Flutter面试题和答案收集,各种知识点的深入研究,学完之后征服你的面试官。

算是flutter最完整题库了

https://juejin.im/post/5ef58a296fb9a07ea76fd8c7

目录

提示

更多的正在更新!

Flutter微信群

上图无法显示点我

Flutter教程网:www.flutterj.com

Flutter交流QQ群:874592746

公众号

关注公众号“Flutter前线”,各种Flutter项目实战经验技巧,干活知识,Flutter面试题答案,等你来领取。

flutter_interview's People

Contributors

ahyangnb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flutter_interview's Issues

Flutter每日一面(面试题四)

  • 1.简单的说说Flutter优缺点以及理念架构:

答案:

优点

  • 热重载(Hot Reload),利用Android Studio直接一个ctrl+s就可以保存并重载,模拟器立马就可以看见效果,相比原生冗长的编译过程强很多;
  • 一切皆为Widget的理念,对于Flutter来说,手机应用里的所有东西都是Widget,通过可组合的空间集合、丰富的动画库以及分层课扩展的架构实现了富有感染力的灵活界面设计;
  • 借助可移植的GPU加速的渲染引擎以及高性能本地代码运行时以达到跨平台设备的高质量用户体验。 简单来说就是:最终结果就是利用Flutter构建的应用在运行效率上会和原生应用差不多。

缺点

  • 不支持热更新;
  • 三方库很少,需要自己造轮子(不过现在越来越多了,社区也越来越强了);
  • dart语言编写,掌握该语言的开发者很少(不过有其他语言基础的掌握起来也特别容易)。

理念架构

Flutter 主要分为 Framework 和 Engine,我们基于Framework 开发App,运行在 Engine 上。Engine 是 Flutter 的独立虚拟机,由它适配和提供跨平台支持,目前猜测 Flutter 应用程序在 Android 上,是直接运行 Engine 上 所以在是不需要Dalvik虚拟机。(这是比kotlin更彻底,抛弃JVM的纠缠? )
  得益于 Engine 层,Flutter 甚至不使用移动平台的原生控件, 而是使用自己 Engine 来绘制 Widget (Flutter的显示单元),而 Dart 代码都是通过 AOT 编译为平台的原生代码,所以 Flutter 可以 直接与平台通信,不需要JS引擎的桥接。同时 Flutter 唯一要求系统提供的是 canvas,以实现UI的绘制。

  • 2.简单的解释下Flutter的FrameWork层和Engine层:

答案:

FrameWork层

Flutter的顶层是用drat编写的框架(SDK),它实现了一套基础库,包含Material(Android风格UI)和Cupertino(iOS风格)的UI界面,下面是通用的Widgets(组件),之后是一些动画、绘制、渲染、手势库等。这个纯 Dart实现的 SDK被封装为了一个叫作 dart:ui的 Dart库。我们在使用 Flutter写 App的时候,直接导入这个库即可使用组件等功能。

Engine层

  • Skia是Google的一个 2D的绘图引擎库,其前身是一个向量绘图软件,Chrome和 Android均采用 Skia作为绘图引擎。Skia提供了非常友好的 API,并且在图形转换、文字渲染、位图渲染方面都提供了友好、高效的表现。Skia是跨平台的,所以可以被嵌入到 Flutter的 iOS SDK中,而不用去研究 iOS闭源的 Core Graphics / Core Animation。Android自带了 Skia,所以 Flutter Android SDK要比 iOS SDK小很多。
  • 第二是Dart 运行时环境
  • 第三文本渲染布局引擎。

image


Flutter每日一面目录大全

Flutter每日一面(面试题二)

  • 1.Flutter绘制流程是怎么样的?

答案:

Flutter只关心向 GPU提供视图数据,GPU的 VSync信号同步到 UI线程,UI线程使用 Dart来构建抽象的视图结构,这份数据结构在 GPU线程进行图层合成,视图数据提供给 Skia引擎渲染为 GPU数据,这些数据通过 OpenGL或者 Vulkan提供给 GPU。

所以 Flutter并不关心显示器、视频控制器以及 GPU具体工作,它只关心 GPU发出的 VSync信号,尽可能快地在两个 VSync信号之间计算并合成视图数据,并且把数据提供给 GPU。

image

  • 2.说下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 不会被重建,只是更新而已。

  • 3.Flutter main future mirotask 的执行顺序是怎么样的?

答案:

普通代码都是同步执行的,结束后会开始检查microtask中是否有任务,若有则执行,执行完继续检查microtask,直到microtask列队为空。最后会去执行event队列(future)。

  • 4.Future和Isolate有什么区别?

答案:

future是异步编程,调用本身立即返回,并在稍后的某个时候执行完成时再获得返回结果。在普通代码中可以使用await 等待一个异步调用结束。

isolate是并发编程,Dartm有并发时的共享状态,所有Dart代码都在isolate中运行,包括最初的main()。每个isolate都有它自己的堆内存,意味着其中所有内存数据,包括全局数据,都仅对该isolate可见,它们之间的通信只能通过传递消息的机制完成,消息则通过端口(port)收发。isolate只是一个概念,具体取决于如何实现,比如在Dart VM中一个isolate可能会是一个线程,在Web中可能会是一个Web Worker。

  • 5.Stream 与 Future是什么关系?

答案:

Stream 和 Future 是 Dart 异步处理的核心 API。Future 表示稍后获得的一个数据,所有异步的操作的返回值都用 Future 来表示。但是 Future 只能表示一次异步获得的数据。而 Stream 表示多次异步获得的数据。比如界面上的按钮可能会被用户点击多次,所以按钮上的点击事件(onClick)就是一个 Stream 。简单地说,Future将返回一个值,而Stream将返回多次值。Dart 中统一使用 Stream 处理异步事件流。Stream 和一般的集合类似,都是一组数据,只不过一个是异步推送,一个是同步拉取。

  • 6.Stream 有哪两种订阅模式?分别是怎么调用的?

答案:

Stream有两种订阅模式:单订阅(single) 和 多订阅(broadcast)。单订阅就是只能有一个订阅者,而广播是可以有多个订阅者。这就有点类似于消息服务(Message Service)的处理模式。单订阅类似于点对点,在订阅者出现之前会持有数据,在订阅者出现之后就才转交给它。而广播类似于发布订阅模式,可以同时有多个订阅者,当有数据时就会传递给所有的订阅者,而不管当前是否已有订阅者存在。

Stream 默认处于单订阅模式,所以同一个 stream 上的 listen 和其它大多数方法只能调用一次,调用第二次就会报错。但 Stream 可以通过 transform() 方法(返回另一个 Stream)进行连续调用。通过 Stream.asBroadcastStream() 可以将一个单订阅模式的 Stream 转换成一个多订阅模式的 Stream,isBroadcast 属性可以判断当前 Stream 所处的模式。

  • 7.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('晚上还没吃饭');
}
  • 8.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。

这些状态的引入,主要是为了解决多个部件之间的交互和部件自身状态的维护。

  • 9.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对象。

  • 10.Widget 唯一标识Key有那几种?

答案:

在flutter中,每个widget都是被唯一标识的。这个唯一标识在build或rendering阶段由框架定义。该标识对应于可选的Key参数,如果省略,Flutter将会自动生成一个。

在flutter中,主要有4种类型的Key:GlobalKey(确保生成的Key在整个应用中唯一,是很昂贵的,允许element在树周围移动或变更父节点而不会丢失状态)、LocalKey、UniqueKey、ObjectKey。

  • 11.Navigator是什么,为什么Navigator可以实现无需上下文路由导航?

答案:

Navigator是在Flutter中负责管理维护页面堆栈的导航器。MaterialApp在需要的时候,会自动为我们创建Navigator。Navigator.of(context),会使用context来向上遍历Element树,找到MaterialApp提供的NavigatorState再调用其push/pop方法完成导航操作。

所以如果在MaterialApp的navigatorKey属性内设置好一个Key就可以直接使用这个Key来进行路由导航,无需上下文。


下一篇:Flutter每日一面(面试题三)

Flutter每日一面目录大全

Flutter每日一面(面试题五)

  • 1.你是如何解决asset数组图片滑动出现白屏问题的?

答案:

在初始化的时候就加载指定asset图片,而不是在需要展示的时候才开始加载。

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) async {
     // _imageUrls 就是数组的Asset图片地址
      _imageUrls.forEach((image) {
        precacheImage(AssetImage(image), context);
      });
    });
  }

Flutter每日一面(面试题三)

  • 1.Dart 语言的特性是怎么样的?

答案:

  • Productive(生产力高,Dart的语法清晰明了,工具简单但功能强大)

  • Fast(执行速度快,Dart提供提前优化编译,以在移动设备和Web上获得可预测的高性能和快速启动。)

  • Portable(易于移植,Dart可编译成ARM和X86代码,这样Dart移动应用程序可以在iOS、Android和其他地方运行)

  • Approachable(容易上手,充分吸收了高级语言特性,如果你已经知道C++,C语言,或者Java,你可以在短短几天内用Dart来开发)

  • Reactive(响应式编程)

  • 2.Dart 语言有哪些重要的概念?

答案:

  • 在Dart中,一切都是对象,所有的对象都是继承自Object

  • Dart是强类型语言,但可以用var或 dynamic来声明一个变量,Dart会自动推断其数据类型,dynamic类似c#

  • 没有赋初值的变量都会有默认值null

  • Dart支持顶层方法,如main方法,可以在方法内部创建方法

  • Dart支持顶层变量,也支持类变量或对象变量

  • Dart没有public protected private等关键字,如果某个变量以下划线(_)开头,代表这个变量在库中是私有的

  • 3.说下mixin extends implement 之间的关系?

答案:

继承(关键字 extends)、混入 mixins (关键字 with)、接口实现(关键字 implements)。这三者可以同时存在,前后顺序是extends -> mixins -> implements

Flutter中的继承是单继承,子类重写超类的方法要用@Override,子类调用超类的方法要用super。

在Flutter中,Mixins是一种在多个类层次结构中复用类代码的方法。mixins的对象是类,mixins绝不是继承,也不是接口,而是一种全新的特性,可以mixins多个类,mixins的使用需要满足一定条件。

  • 4.使用mixins的条件是什么?

答案:

随着Dart版本一直在变,这里讲的是Dart2.1中使用mixins的条件:

  • mixins类只能继承自object

  • mixins类不能有构造函数

  • 一个类可以mixins多个mixins类

  • 可以mixins多个类,不破坏Flutter的单继承

  • 5.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{
}

下一篇:Flutter每日一面(面试题四)

Flutter每日一面目录大全

Flutter每日一面(面试题一)

  • 1.Flutter屏幕算法面试题基础(一):

假如蓝湖设计图给你一张轮播图,宽度是 x 高度是 y(x px * y px),左右间隔是t,如何使用屏幕算法适配全机型屏幕宽和高?

其实这种形式是可以直接用AspectRatio写宽高比,但是面试官要求手动算出来,可能这里答案不止一个,如果大家有更好的可以在下方评论出来。

答案:

宽度:整宽 - t * 2(左右的)。
高度:(整宽 - t * 2 ) * y / x。

  • 2.Flutter屏幕算法面试题基础(二):

假如蓝湖设计图给你一个未知数据数量有规则的列表视图,要求一行显示5个,每个间隔为10(含上下),最外边距margin左右都为20,高度为50,多出的数据继续往下排并向左对齐,适配任何机型,你会使用什么组件?怎么做适配?

答案:

使用组件:Wrap
spacing和runSpacing都设置为10间隔,
然后Item的高度设置为50,宽度算法为:
( 整宽 - (外边的margin + 内边的space) ) / 5

  • 3 isolate是怎么进行通信和实例化的?

  • 答案:

isolate线程之间的通信主要通过port来进行,这个port消息传递过程是异步的。通过dart源码可以看出,实例化一个isolate的过程包括:
1.实例化isolate结构体。
2.在堆中分配线程内存。
3.配置port等过程。

代码示例:
下面是一个isolate的例子,例子中新建了一个isolate,并且绑定了一个方法网络请求和数据解析处理,并通过port将处理好的数据返回给调用方。

loadData() async {
  // 通过spawn新建一个isolate,并绑定静态方法
  ReceivePort receivePort = ReceivePort();
  await Isolate.spawn(dataLoader, receivePort.sendPort);

  // 获取新的isolate监听port
  SendPort sendPort = await receivePort.first;
  //调用sendReceive自定义方法
  List dataList = await sendReceive(sendPort,
      'http://www.flutterj.com');
  print('dataList $dataList');
}

// isolate绑定方法
static dataLoader(SendPort sendPort) async {
  // 创建监听port,并将sendPort传给外界来调用
  ReceivePort receivePort = ReceivePort();
  sendPort.send(receivePort.sendPort);
// 监听外界调用
  await for (var msg in receivePort) {
    String requestURL = msg[0];
    SendPort callbackPort = msg[1];

    Client client = Client();
    Response response = await client.get(requestURL);
    List dataList = json.decode(response.body);
// 回调返回值给调用者
    callbackPort.send(dataList);
  }
}

// 创建自己的监听port,并且向新的isolate发送消息
Future sendReceive(SendPort sendPort, String url) {
  ReceivePort receivePort = ReceivePort();
  sendPort.send([url, receivePort.sendPort]);
// 接收到返回值, 返回给调用者
  return receivePort.first;
}
  • 4.Flutter是怎么实现热重载的,原理和过程是怎么样的?

  • 答案:

Flutter热重载是基于State的,也就是我们在代码中经常出现的setState方法,通过这个来修改后,会执行相应的build方法,这就是热重载的基本过程。

实现源码在下面路径中,包含文件run_cold.dartrun_hot.dart两个文件,前者负责冷启动,后者负责热重载。

~/flutter/packages/flutter_tools/lib/src/run_hot.dart

热重载实现过程:

代码在run_hot.dart文件中,HotRunner负责具体代码执行。
当Flutter热重载时,调用restart函数,函数内部会传入一个fullRestart的bool类型变量。
热重载分为全量和非全量,fullRestart参数金牛是表示是否为全量。
以非全量热重载为例,函数的fullRestart会传入false,根据传入false参数,下面是哪部核心代码。

Future<OperationResult> restart(
    {bool fullRestart = false,
    bool pauseAfterRestart = false,
    String reason}) async {
  if (fullRestart) {
    // .....
  } else {
    final bool reloadOnTopOfSnapshot = _runningFromSnapshot;
    final String progressPrefix =
        reloadOnTopOfSnapshot ? 'Initializing' : 'Performing';
    final Status status = logger.startProgress('$progressPrefix hot reload...',
        progressId: 'hot.reload');
    OperationResult result;
    try {
      result = await _reloadSources(pause: pauseAfterRestart, reason: reason);
    } finally {
      status.cancel();
    }
  }
}

调用Restart函数后,内部会调用_reloadSources函数,去执行内部逻辑。

执行流程图:
image

图解:

在_reloadSources函数内部,会调用_updateDevFs函数,函数内部会扫描修改的文件,并将修改的文件进行对比,随后将被改动代码生成一个kernel files文件。
然后通过HTTP Server将生成的kernel files文件发送给Dart VM虚拟机,虚拟机拿到kernel文件后会调用_reloadSources函数进行资源重载,将kernel文件注入正在运行的Dart VM中,当资源重载完成后,会调用RPC接口触发Widgets的重绘。

  • 5.为什么说Flutter性能好?说下和其他跨平台的本质区别!

  • 答案:

与用于构建移动应用程序的其他大多数框架不同,Flutter是重写了一整套包括底层渲染逻辑和上层开发语言的完整解决方案。这样不仅可以保证视图渲染在Android和iOS上的高度一致性,在代码执行效率和渲染性能上也可以媲美原生App的体验。这,就是Flutter和其他跨平台方案的本质区别。

  • 6.Flutter是怎么完成组件渲染的?

  • 答案:

在计算机系统中,图像的显示需要CPU、GPU和显示器一起配合完成CPU负责图像数据计算,GPU负责图像数据渲染,而显示器则负责最终图像显示。CPU把计算好的、需要显示的内容交给GPU,由GPU完成渲染后放入帧缓冲区,随后视频控制器根据垂直同步信号以每秒60次的速度,从帧缓冲区读取帧数据交由显示器完成图像显示。操作系统在呈现图像时遵循了这种机制。

而Flutter作为跨平台开发框架也采用了这种底层方案,UI线程使用Dart语言来构建视图结构数据,这些数据会在GPU线程进行图层合成,随后交给图像渲染引擎Skia加工成GPU数据,而这些数据会通过OpenGL最终提供给GPU渲染。

可以看到Flutter用了计算机最基本的图像渲染技术,摒弃其他一些通道和过程,用最直接的方式完成了图形显示,自然性能也就得到了保障。


下一篇:Flutter每日一面(面试题二)

Flutter每日一面目录大全

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.