Flutter是Google推出的一套开源跨平台UI框架,能够快速地在Android、iOS和Web平台上构建高质量的原生用户界面。在过去的一年里,Flutter的更新频率是至关的快,也有不少的公司开始使用它来进行跨平台应用开发,能够说,将Flutter称为2019年最流行的跨平台技术也不为过。前端
在研究了Hybrid APP、React Native和Weex等技术以后,为在今年的早些时候也入了Flutter的坑。总的来讲,无论是从社群和社区的活跃来看,仍是从技术的水准上来看,Flutter无疑是最优秀的,特别是Google将Flutter列为重点推广项目以后,全世界掀起了一股学习Flutter的热潮。面试
在国内,除了阿里、腾讯、美团等大厂外,国内不少的中小团队也开始使用Flutter来做为移动应用开发的首选,而且不少公司在移动招聘方面也要求具备Flutter开发的背景。Flutter 的面试题主要分为两个Dart和Flutter部分,下面是一些常见的面试题。编程
1. Dart 当中的 「..」表示什么意思? Dart 当中的 「..」意思是 「级联操做符」,为了方便配置而使用。「..」和「.」不一样的是 调用「..」后返回的至关因而 this,而「.」返回的则是该方法返回的值 。安全
2. Dart 的做用域 Dart 没有 「public」「private」等关键字,默认就是公开的,私有变量使用 下划线 _开头。bash
3. Dart 是否是单线程模型?是如何运行的? Dart 是单线程模型,运行的的流程以下图。 网络
当Flutter应用启动后,消息循环机制便启动了。首先会按照先进先出的顺序逐个执行微任务队列中的任务,当全部微任务队列执行完后便开始执行事件队列中的任务,事件任务执行完毕后再去执行微任务,如此循环往复,生生不息。数据结构
4. Dart 是如何实现多任务并行的? 前面说过, Dart 是单线程的,不存在多线程,那如何进行多任务并行的呢?其实,Dart的多线程和前端的多线程有不少的类似之处。Flutter的多线程主要依赖Dart的并发编程、异步和事件驱动机制。 多线程
5. 说一下Dart异步编程中的 Future关键字? 前面说过,Dart 在单线程中是以消息循环机制来运行的,其中包含两个任务队列,一个是“微任务队列” microtask queue,另外一个叫作“事件队列” event queue。架构
在Java并发编程开发中,常常会使用Future来处理异步或者延迟处理任务等操做。而在Dart中,执行一个异步任务一样也可使用Future来处理。在 Dart 的每个 Isolate 当中,执行的优先级为 : Main > MicroTask > EventQueue。并发
6. 说一下Dart异步编程中的 Stream数据流? 在Dart中,Stream 和 Future 同样,都是用来处理异步编程的工具。它们的区别在于,Stream 能够接收多个异步结果,而Future 只有一个。 Stream 的建立可使用 Stream.fromFuture,也可使用 StreamController 来建立和控制。还有一个注意点是:普通的 Stream 只能够有一个订阅者,若是想要多订阅的话,要使用 asBroadcastStream()。
7. Stream 有哪两种订阅模式?分别是怎么调用的? Stream有两种订阅模式:单订阅(single) 和 多订阅(broadcast)。单订阅就是只能有一个订阅者,而广播是能够有多个订阅者。这就有点相似于消息服务(Message Service)的处理模式。单订阅相似于点对点,在订阅者出现以前会持有数据,在订阅者出现以后就才转交给它。而广播相似于发布订阅模式,能够同时有多个订阅者,当有数据时就会传递给全部的订阅者,而无论当前是否已有订阅者存在。
Stream 默认处于单订阅模式,因此同一个 stream 上的 listen 和其它大多数方法只能调用一次,调用第二次就会报错。但 Stream 能够经过 transform() 方法(返回另外一个 Stream)进行连续调用。经过 Stream.asBroadcastStream() 能够将一个单订阅模式的 Stream 转换成一个多订阅模式的 Stream,isBroadcast 属性能够判断当前 Stream 所处的模式。
8. await for 如何使用? await for是不断获取stream流中的数据,而后执行循环体中的操做。它通常用在直到stream何时完成,而且必须等待传递完成以后才能使用,否则就会一直阻塞。
Stream<String> stream = new Stream<String>.fromIterable(['不开心', '面试', '没', '过']);
main() async{
await for(String s in stream){
print(s);
}
}
复制代码
9. 说一下 mixin机制? mixin 是Dart 2.1 加入的特性,之前版本一般使用abstract class代替。简单来讲,mixin是为了解决继承方面的问题而引入的机制,Dart为了支持多重继承,引入了mixin关键字,它最大的特殊处在于: mixin定义的类不能有构造方法,这样能够避免继承多个类而产生的父类构造方法冲突。
mixins的对象是类,mixins毫不是继承,也不是接口,而是一种全新的特性,能够mixins多个类,mixins的使用须要知足必定条件。
1. 请简单介绍下Flutter框架,以及它的优缺点? Flutter是Google推出的一套开源跨平台UI框架,能够快速地在Android、iOS和Web平台上构建高质量的原生用户界面。同时,Flutter仍是Google新研发的Fuchsia操做系统的默认开发套件。在全世界,Flutter正在被愈来愈多的开发者和组织使用,而且Flutter是彻底免费、开源的。Flutter采用现代响应式框架构建,其中心思想是使用组件来构建应用的UI。当组件的状态发生改变时,组件会重构它的描述,Flutter会对比以前的描述,以肯定底层渲染树从当前状态转换到下一个状态所须要的最小更改。
优势
缺点
2. 介绍下Flutter的理念架构 其实也就是下面这张图。
3. 介绍下FFlutter的FrameWork层和Engine层,以及它们的做用
Flutter的FrameWork层是用Drat编写的框架(SDK),它实现了一套基础库,包含Material(Android风格UI)和Cupertino(iOS风格)的UI界面,下面是通用的Widgets(组件),以后是一些动画、绘制、渲染、手势库等。这个纯 Dart实现的 SDK被封装为了一个叫做 dart:ui的 Dart库。咱们在使用 Flutter写 App的时候,直接导入这个库便可使用组件等功能。
Flutter的Engine层是Skia 2D的绘图引擎库,其前身是一个向量绘图软件,Chrome和 Android均采用 Skia做为绘图引擎。Skia提供了很是友好的 API,而且在图形转换、文字渲染、位图渲染方面都提供了友好、高效的表现。Skia是跨平台的,因此能够被嵌入到 Flutter的 iOS SDK中,而不用去研究 iOS闭源的 Core Graphics / Core Animation。Android自带了 Skia,因此 Flutter Android SDK要比 iOS SDK小不少。
4. 介绍下Widget、State、Context 概念
5. 简述Widget的StatelessWidget和StatefulWidget两种状态组件类
StatelessWidget: 一旦建立就不关心任何变化,在下次构建以前都不会改变。它们除了依赖于自身的配置信息(在父节点构建时提供)外再也不依赖于任何其余信息。好比典型的Text、Row、Column、Container等,都是StatelessWidget。它的生命周期至关简单:初始化、经过build()渲染。
StatefulWidget: 在生命周期内,该类Widget所持有的数据可能会发生变化,这样的数据被称为State,这些拥有动态内部数据的Widget被称为StatefulWidget。好比复选框、Button等。State会与Context相关联,而且此关联是永久性的,State对象将永远不会改变其Context,即便能够在树结构周围移动,也仍将与该context相关联。当state与context关联时,state被视为已挂载。StatefulWidget由两部分组成,在初始化时必需要在createState()时初始化一个与之相关的State对象。
6. StatefulWidget 的生命周期 Flutter的Widget分为StatelessWidget和StatefulWidget两种。其中,StatelessWidget是无状态的,StatefulWidget是有状态的,所以实际使用时,更多的是StatefulWidget。StatefulWidget的生命周期以下图。
7. 简述Widgets、RenderObjects 和 Elements的关系 首先看一下这几个对象的含义及做用。
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. 什么是状态管理,你了解哪些状态管理框架? Flutter中的状态和前端React中的状态概念是一致的。React框架的核心思想是组件化,应用由组件搭建而成,组件最重要的概念就是状态,状态是一个组件的UI数据模型,是组件渲染时的数据依据。
Flutter的状态能够分为全局状态和局部状态两种。经常使用的状态管理有ScopedModel、BLoC、Redux / FishRedux和Provider。详细使用状况和差别能够自行了解。
9. 简述Flutter的绘制流程
Flutter的绘制流程以下图所示。
10. 简述Flutter的线程管理模型 默认状况下,Flutter Engine层会建立一个Isolate,而且Dart代码默认就运行在这个主Isolate上。必要时可使用spawnUri和spawn两种方式来建立新的Isolate,在Flutter中,新建立的Isolate由Flutter进行统一的管理。 事实上,Flutter Engine本身不建立和管理线程,Flutter Engine线程的建立和管理是Embeder负责的,Embeder指的是将引擎移植到平台的中间层代码,Flutter Engine层的架构示意图以下图所示。
在Flutter的架构中,Embeder提供四个Task Runner,分别是Platform Task Runner、UI Task Runner Thread、GPU Task Runner和IO Task Runner,每一个Task Runner负责不一样的任务,Flutter Engine不在意Task Runner运行在哪一个线程,可是它须要线程在整个生命周期里面保持稳定。
11. Flutter 是如何与原生Android、iOS进行通讯的? Flutter 经过 PlatformChannel 与原生进行交互,其中 PlatformChannel 分为三种:
同时 Platform Channel 并不是是线程安全的 ,更多详细可查阅闲鱼技术的 《深刻理解Flutter Platform Channel》
12. 简述Flutter 的热重载 Flutter 的热重载是基于 JIT 编译模式的代码增量同步。因为 JIT 属于动态编译,可以将 Dart 代码编译成生成中间代码,让 Dart VM 在运行时解释执行,所以能够经过动态更新中间代码实现增量同步。
热重载的流程能够分为 5 步,包括:扫描工程改动、增量编译、推送更新、代码合并、Widget 重建。Flutter 在接收到代码变动后,并不会让 App 从新启动执行,而只会触发 Widget 树的从新绘制,所以能够保持改动前的状态,大大缩短了从代码修改到看到修改产生的变化之间所须要的时间。
另外一方面,因为涉及到状态的保存与恢复,涉及状态兼容与状态初始化的场景,热重载是没法支持的,如改动先后 Widget 状态没法兼容、全局变量与静态属性的更改、main 方法里的更改、initState 方法里的更改、枚举和泛型的更改等。
能够发现,热重载提升了调试 UI 的效率,很是适合写界面样式这样须要反复查看修改效果的场景。但因为其状态保存的机制所限,热重载自己也有一些没法支持的边界。
更多详细的资料能够参考Flutter的Hot Reload是如何实现的
参考资料
1,Flutter 应用程序调试
2,Flutter For Web入门实战
3,Flutter开发之路由与导航
4,Flutter 必备开源项目
5,Flutter混合开发
6,Flutter的Hot Reload是如何作到的
7,《Flutter in action》开源
8,Flutter开发之JSON解析
9,Flutter开发之基础Widgets
10,Flutter开发之导航与路由管理
11,Flutter开发之网络请求
12,Flutter基础知识
13,Flutter开发之Dart语言基础
14,Flutter入门与环境搭建
15,移动跨平台方案对比:WEEX、React Native、Flutter和PWA