Flutter面试

Dart语言都是值传递,每次调用函数都是传递对象的内存地址,而不是复制对象

优点:热重载(Hot Reload)

缺点:不支持热更新,三方库有限,需要自己造轮子

Flutter的FrameWork层是用Drat编写的框架(SDK),它实现了一套基础库,组件库,比Engine上层

Flutter的Engine层是Skia 2D的绘图引擎库,跟GPU交互

StatelessWidget: 一旦创建就不关心任何变化,在下次构建之前都不会改变;

StatefulWidget: 在生命周期内,该类Widget所持有的数据可能会发生变化,这样的数据被称为State;

1.生命周期:

StatefulWidget ---->  initState  ----->  didChangeDependencies  ----> build (中间会插入 didUpdateWidget)  ----> deactivate  ---->  dispose


2. 这个就是Flutter面向对象

继承 extends   混入mixins  接口实现 implements

优先继承,其次混入,最后接口实现

mixins不能有构造函数,其实也是单继承;

抽象类abstract:父类可以只声明,不实现;由子类去实现;

私有变量加_,其他默认公开

3.Flutter渲染三棵树

WidgetTree:存放渲染内容,只是一个配置数据结构;

Element:中间层,同时持有Widget和RenderObject,会去遍历视图树;

RenderObject:负责真正的界面布局和渲染,包含大小和布局等信息,实例化RenderObject很耗时;

4.Widget分类

组合类:StatefulWidget和StatelessWidget

代理类:inheritedWidget和parentDataWidget:通过context获取共享状态

绘制类:RenderObjectWidget:布局相关方法调用顺序:layout(准备布局) --->performResize(计算大小)  ---> performLayout(开始布局) ---> markNeedPaints(是否需要重绘)

5.单订阅和多订阅(Stream)

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

6.Widget   State   Context

Widget:Widget就是可视化组件,里面的结构是树状的,所以说是WidgetTree,父Widget和子Widget;

State:是StatefulWidget的实例化行为,可以交互和干预Widget的状态和布局,任何变更都会触发重建Widget;

Context:每一个Widget都会有对应的Widget,用来描述它的位置引用,是Widget树的一部分;

7.Isolate执行顺序和Future,Stream的区别

Main(主事件)  --->    MicroTask(微事件)   ---->  EventQueue(事件循环);

最后就在微事件和事件循环中反复循环,并且遵循先进先出

Isolate实际是一个隔离的Dart上下文环境(容器)。并且不同的Isolate线程之间的通信通过port来异步进行,在内存上是隔离开的

耗时长的并且影响应用流畅性的就用Isolate(比如图片处理,JSON解析),如果耗时短的就用Future;

Isolate.spawn() 和Isolate.exit()

Future表示延迟运行的对象,用来表示一个潜在的值返回或错误返回,这个返回值将在未来的某个时刻才可用。Future的调用者可以注册回调,一旦返回值或错误可用,就可以通过回调函数对其进行处理。

Future.delayed:创建在延迟一定时间后运行的Future

Future.microtask:创建包含使用scheduleMicrotask异步调用计算的结果的Future

Future.value:创建一个有值返回的Future

Future.sync:返回包含立即调用计算结果的future


Stream:在Dart中,Stream 和 Future 一样,都是用来处理异步编程的工具。它们的区别在于,Stream 可以接收多个异步结果,而Future 只有一个。多个是asBroadcastStream()。

await for 如何使用?

await for是不断获取stream流中的数据,然后执行循环体中的操作。它一般用在直到stream什么时候完成,并且必须等待传递完成之后才能使用,不然就会一直阻塞

8.组件渲染怎么完成的

通过代码来构建视图结构数据,然后通过Skia图像引擎加工成GPU数据,最后通过OpenGL提供给GPU渲染

9.PlatformView原理

Platform view 就是 AndroidView 和 UIKitView 的总称,允许将native view嵌入到Widget体系中,完成Dart对native view的控制;

Platform view 是在 native 侧渲染的,并且底层实际是使用texture实现,通过_textureId来展示,所以Platform view开销很大。因为需要从GPU切换到CPU,然后再切换到GPU,所以尽量避免使用Platform view;一般使用是webView;

Platform view大小由父节点的大小来控制,所以需要用Expanded包裹,不然就是父视图的大小;


10.Flutter 线程管理模型

线程管理模型:Flutter Engine会创建一个isolate,dart代码运行在这个主isolate上,新创建的isolate由flutter进行统一管理。

Flutter的线程管理由一个叫Embeder的中间层组件控制,Embeder提供了四个Task,分别是UITaskRunner、IOTaskRunner、GPUTaskRunner、platformTaskRunner

UITaskRunner:负责绑定渲染相关的操作,如timer,microtask,异步io操作;

IOTaskRunner:处理图片数据,为gpu渲染做准备,比如读取磁盘压缩图片的格式,将解压成gpu能处理的格式,并传给gpu,因其比较消耗性能所以单独开一个线程。

GPUTaskRunner:用于执行gpu指令,负责将layer tree提供的信息转换为平台可执行的gpu指令

platformTaskRunner:所有接口调用都使用该接口,长时间卡顿将会被watchdog强杀。


11.Flutter状态管理

状态管理:

view:界面层,主要是UI

Logic:逻辑层,主要处理业务逻辑

State:状态层,主要处理页面所需数据状态

Action:行为层,主要处理交互事件

Reducer:这个层级,是专门用于处理数据变化的

Provider:是最为推荐的状态管理库,对InheritedWidget进行了上层封装,解决原生setState方案的props臃肿、展示与逻辑耦合问题;Provider将页面分为业务和视图两层,并定义Notifier、Consumer两个核心概念

Notifier负责实现业务逻辑,且在数据更新时发出通知。

Consumer负责实现界面逻辑,并在数据更新时更新自身,以及用户交互时调用Notifier方法。

12.Flutter如何与原生Android,iOS进行通信

Flutter通过PlatformChannel与原生进行交互,总共有三种:

BasicMessageChannel:传递字符串和半结构化信息;

MethodChannel:传递方法调用;一般就是MethodChannel.result;

EventChannel:传递数据流(event streams);

13.Flutter的热重载

基于JIT编译模式的代码增量同步,总共分为五步:

扫描工程改动;增量编译;推送更新;代码合并;Widget重建;

所以并不会让APP重新启动,缩短时间;

14.Flutter布局

Row (行布局)

Column (列布局)

Container (容器)

ListView(类似iOS中的UITableView):GlobalKey,通过 key 去获取到控件对象的 BuildContext(其实就是RenderObject);

15.Flutter集成声网

在initState方法里初始化RtcEngine对象,通过initAgoraRtc和addAgoraEventHandlers,和joinChannel;

在回调中有加入频道,离开频道,用户加入频道,第一次个视频帧渲染回调;

聊天相关的是单独的createClient,通过AgoraRtmClient来管理用户聊天等相关信息


-------------------------------------------------------------------------------------------------

Dart相关

1.Dart是类型安全的语言,它会自动做类型转换;并且会有静态检查和运行时检查;

所以它的维护性高,编译器就可以显示类型错误;

2.类型

Number  String  Bool  List  Set  Map  Null

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容