一、flutter与原生通信,三种通道的区别
1.1 MethodChannel
Flutter与Native端相互调用,调用后返回结果
可以Native端主动调用,也可以Flutter主动调用,属于双向通信
此种方式最为常见,Native端调用需要在主线程中执行
1.2 BasicMessageChannel
用于使用指定的编解码器对消息进行编码和解码
属于双向通信,可以以Native端主动调用,也可以Flutter主动调用
1.3 EventChannel
用于数据流(event stream)的通信,Native端主动发送数据给Flutter
通常用于状态端监听,比如网络变化、传感器数据等
原文链接:https://blog.csdn.net/Calvin_zhou/article/details/118888030
二、flutter自定义组件,生命周期
image.png
image.png
Flutter的生命周期包含一下几个阶段:
CreateState 该函数为StatefulWidget创建State时调用的方法,当StatefulWidget被调用时候会立即调用此方法。
initState 该方法为State初始化调用,因此在此期间可以执行变量的初始化,还可以进行与服务端的初始化,获取到服务端数据之后调用setState方法更新组件。
didChangeDependencies 该函数是在该组件依赖的全局State发生变化的时候调用。
build 该函数主要是渲染Widget,会被调用多次,最好只做返回Widget相关的事情。
reassemble 只要是提供开发阶段使用,只有在debug模式下热重载才会调用。可以添加一些代码来调试。
didUpdateWidget 此方法在组件重新构建,比如热更新,父组件发生Build时候调用此方法,其次此方法会导致本组件的build方法被调用。
deactivate 在组件被移除时候调用,如果组件被移除,未被插入到其他组件。那么会调用dispose永久移除。
1、initState调用次数:1次插入渲染树时调用,只调用一次,widget创建执行的第一个方法,这里可以做一些初始化工作,比如初始化State的变量。2、didChangeDependencies调用次数:多次初始化时,在initState()之后立刻调用当依赖的InheritedWidget rebuild,会触发此接口被调用实测在组件可见状态变化的时候会调用3、build调用次数:多次 初始化之后开始绘制界面setState触发的时候会 4、didUpdateWidget调用次数:多次组件状态改变时候调用5、deactivate当State对象从树中被移除时,会调用此回调,会在dispose之前调用。页面销毁的时候会依次执行:deactivate > dispose6、dispose调用次数:1次当State对象从树中被永久移除时调用;通常在此回调中释放资源。7、reassemble在热重载(hot reload)时会被调用,此回调在Release模式下永远不会被调用
原文链接:https://blog.csdn.net/yoonerloop/article/details/121003373
1.WidgetsBindingObserver
和App生命周期有关AppLifecycleState
1、resumed可见并能响应用户的输入,同安卓的onResume2、inactive 处在并不活动状态,无法处理用户响应,同安卓的onPause3、paused不可见并不能响应用户的输入,但是在后台继续活动中,同安卓的onStop下面是生命周期:初次打开widget时,不执行AppLifecycleState的回调;按home键或Power键, AppLifecycleState inactive---->AppLifecycleStatepause从后台到前台:AppLifecycleState inactive--->ApplifecycleStateresumedback键退出应用: AppLifecycleState inactive--->AppLifecycleStatepaused
原文链接:https://blog.csdn.net/yoonerloop/article/details/121003373
//初始化一些变量voidonCreate(){}//onResume 只要页面切换到栈顶,都会调用此方法voidonResume(){_isResume=true;_isPause=false;}//页面被覆盖,暂停voidonPause(){_isResume=false;_isPause=true;}voidonDestroy(){}</blockcode>
LifeCycleInnerState
2.RouteAware
监听路由变化
RouteObserver 是一个配合RouteAware的一个类,通过这个类可以通知到当前页面应该执行那种生命周期方法,否则只混入RouteAware是不能执行的。另外还有RouteObserver需要注册在MaterialApp中,这样才能在导航的过程中执行到对应的生命周期方法。navigatorObservers
@overridevoiddidPush(){super.didPush();//从其他页面跳转到当前页面log("didPush");_isTop=true;}@overridevoiddidPushNext(){//从当前页面跳转到下一页之后才会调用?super.didPushNext();log("didPushNext");onPause();//在本页面执行onPause()_isTop=false;}@overridevoiddidPop(){//从当前页面退回当上一页面super.didPop();//poponPause();//在当前页执行onPause()}@overridevoiddidPopNext(){super.didPopNext();//从其他页面Pop之后,进入到当前页面onResume();//在当前页面执行onResume()_isTop=true;}
原文链接:https://blog.csdn.net/happiness365/article/details/122782217
三、flutter树结构
Widget树、Element树、RenderObject树
并不是所有的Widget都会被独立渲染!只有继承RenderObjectWidget的才会创建RenderObject对象
每一个Widget都会创建一个Element对象
隐式调用createElement方法。Element加入Element树种
它会创建三种Element
1.RenderElement主要是创建RenderObject对象继承RenderObjectWidget的Widget会创建RenderElement创建RanderElementFlutter会调用mount方法,调用createRanderObject方法2.StatefulElement继承ComponentElementStatefulWidget会创建StatefulElement调用createState方法,创建State将Widget赋值给state调用state的build方法 并且将自己(Element)传出去build里面的context就是Widget的Element!3.StatelessElement继承ComponentElementStatelessWidget会创建StatelessElement主要就是调用build方法 并且将自己(Element)传出去</blockcode>
四、flutter 状态管理,provider
状态管理就是一些变量的管理,而这些变量需要在多个路由界面中重复使用,所以就有了状态管理。
如果多个界面需要重复数据时,当这些界面频繁跳转时,没有全局状态管理,那就需要每次跳转路由界面都需要传值一次达到保存数据的目的,当有了全局状态管理,每次需要读取或者改变这些数据时,则可以调用公用方法获取或修改,因此可以大大减少工作量并提升应用性能
一个model类可以有多个属性,一个app可以有多个model类
全局管理类,不见得用model结尾,但是我个人喜欢用model来存储数据
model类必须要继承ChangeNotifier类,否则无法刷新数据
model管理的状态,只有get方法,修改他的值是通过单独的方法进行修改的,在修改后要调用notifyListeners方法
链接:https://www.jianshu.com/p/7d392f696de3
image.png
五、Future是什么
Future代表异步执行
async:在方法体前面是使用,定义该方法为一个异步方法。
await:等待并获得异步表达式的执行结果,并且给关键字只能在async修饰的方法中。
Future是单线程,先执行完全部微任务,再执行队列任务
Future修饰的关键字,会将事件加入到队列任务中
Future如何获取异步的值:通过then()方法 Future如何处理异常:通过catchError()或者在then()中传入命名参数onErrorasync和wait的关键的作用是什么:async声明一个异步方法,wait等待异步任务完成;简单来讲就是同步的方式编写异步代码。 如何捕获和处理async中的异常:需要使用try/catch来捕获以及处理程序运行中的异常。
原文链接:https://blog.csdn.net/mrRuby/article/details/122563629
六、UI或文本溢出
文本用TextOverflow进行溢出属性处理
列表溢出,使用Wrap(//流式布局处理
在text 外层包裹一个Expanded 它会将宽高设定为余下空间
1,Row报overflowed的解决办法
在要展示内容外包一层Expanded
2,Column报overflowed的解决办法
在Column外包一层SingleChildScrollView
在Scaffold下设置resizeToAvoidBottomInset : false
七、flutter性能优化
1.widget build()方法避免执行重复耗时的非必要操作
避免在widget或者state的build()方法中进行重复且耗时的非必要工作,因为当父 widget 重建时,子 widget 的 build() 方法会被频繁地调用。因此确保非必要的耗时工作不放在build()方法中。
2.控制widget setState()的重建范围
在StatefulWidget中调用setState()会引起该widget的重建,会调用state的build()方法。当一个页面只有一个StatefulWidget,把全部widget的状态都放在这个StatefulWidget,并且该StatefulWidget为页面最顶端的父widget时,setState方法会让整个页面的widget重建。因此,将一个页面中的widget进行多个StatefulWidget的状态划分,每个StatefulWidget只负责自己的状态维护,将大大缩小flutter页面绘制范围。
3.控制widget重建次数
不会改变的widget使用const,如Text、Icon、Image等,这样可以复用这部分widget,不会导致widget重建
动画使用AnimatedBuilder时,将不需要动的子widget赋值给child参数,builder方法中使用该child,可以做到复用子widget,以避免在动画过程中重建其后代 widget。
使用CustomPaint自定义组件的时候,使用重写shouldRepaint方法,返回false即不重绘,true为重绘,我们可以根据条件返回true,减少自定义组件的重绘次数
4.尽量避免saveLayer操作
saveLayer方法是Flutter框架中最重量的操作之一。更新屏幕时这个方法很有用,但它可能使应用变慢,如果不是必须的话,应该避免使用这个方法。即便没有显式地调用saveLayer,也可能在其他操作中间接调用了该方法。
有两个方法可以检查页面是否使用saveLayer,
1.可以使用在MeterialApp中时使用checkerboardOffscreenLayers属性开关来检查当前界面是否使用了saveLayer,打开开关之后,运行应用并检查是否有图像的轮廓闪烁。如果有新的帧渲染的话,容器就会闪烁;
2.使用flutter screenshot --type=skia --observatory-url=这里填timeline的观察台地址,生成skp文件,再上传到https://debugger.skia.org/,就可详细分析页面中的saveLayer的调用,推荐该方法,第一种方法有的saveLayer无法检查出来。
在官网中可以看到,以下组件会触发saveLayer,应尽量避免使用,寻找其他代替。透明度(Opacity)、裁剪(clipping)、阴影(shadows)以及文字(Text)
5.使用懒加载、按需加载模型Slive
滚动列表中SingleChileScrollView不支持Slive,会直接加载整个子widget,如果滑动部分很长,请使用ListView、gridView等支持按需加载模型的列表,并且使用ListView.builder或者ListView.separated加载子项。
6.使用RepaintBoundary
使用RepaintBoundary,给页面设置重绘范围,将提高我们的性能。比如页面滑动不需要重绘动画,使用RepaintBoundary包住我们的动画widget,页面滑动将不会导致动画重绘。还可以用该widget包住我们的图片,做图片缓存,ListView里面就使用了RepaintBoundary来包住item,缓存item。
7.复用Element
element tree是flutter三棵树之一,我个人把他当作渲染树的manager,widget内部有个canUpdate方法。
原文链接:https://blog.csdn.net/weixin_42468452/article/details/120534954
八、flutter插件开发,原生混合开发
iOS用framework或pod
安卓用aar包接入
使用flutterBooost框架
解决跳转全屏flutter会出现引导页
路由问题,pod的时候将flutterBooost的监听和flutterController释放调
九、flutter网络请求,dio优点
dio是一个强大的Dart Http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时、自定义适配器等...可以说是覆盖了所有涉及到的网络请求。
原生HttpClient发起网络请求非常的复杂,很多东西还需自己手动处理。如果涉及到上传、下载、断点续传等那肯定非常繁琐
每个 Dio 实例都可以添加任意多个拦截器,他们组成一个队列,拦截器队列的执行顺序是FIFO先进先出原则。通过拦
作者:你飞跃俊杰
链接:https://www.jianshu.com/p/ad9f803e4188
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
1、Dart 当中的 「…」表示什么意思?
2、Dart 的作用域
3、Dart 是不是单线程模型?是如何运行的?
4、 说一下 Future?
5、说一下 Stream?
6、说一下 mixin?
7、StatefulWidget 的生命周期
8、 Flutter 如何与 Android iOS 通信?
9、dart是什么,和flutter有什么关系?
10、main()和runApp()函数在flutter的作用分别是什么?有什么关系吗?
11、什么是widget? 在flutter里有几种类型的widget?分别有什么区别?能分别说一下生命周期吗?
12、Hot Restart 和 Hot Reload 有什么区别吗?
13、在flutter里streams是什么?有几种streams?有什么场景用到它?
14、简单说一下在flutter里async和await?
15、future 和steam有什么不一样?
16、什么是flutter里的key? 有什么用?
17、在什么场景下使用profile mode?
18、怎么做到只在debug mode运行代码?
19、怎么理解Isolate?
20、await for 如何使用?
21、请简单介绍下Flutter框架,以及它的优缺点?
22、介绍下Flutter的理念架构
23、介绍下FFlutter的FrameWork层和Engine层,以及它们的作用
*24、介绍下Widget、State、Context 概念
*25、简述Widgets、RenderObjects 和 Elements的关系
26、简述Flutter的绘制流程
27、Dart中var与dynamic的区别
28、const和final的区别
29、Dart中??与??=的区别
*30、Widget、Element、RenderObject三者之间的关系
31、Flutter在Debug和Release下分别使用什么编译模式,有什么区别?
32、Flutter 是什么?
33、Flutter 特性有哪些?
34、Flutter 和 Dart的关系是什么?
35、dart的一些重要概念?
36、dart是值传递还是引用传递?
37、 mixin extends implement 之间的关系?
38、Flutter main future mirotask 的执行顺序?
39、Future和Isolate有什么区别?
40、Stream 两种订阅模式?
41、Flutter state生命周期方法之didChangeDependencies 、didUpdateWidget
42、flutter key的种类
1、Dart 当中的 「…」表示什么意思?
Dart 当中的 「…」意思是 「级联操作符」,为了方便配置而使用。
「…」和「.」不同的是 调用「…」后返回的相当于是 this,而「.」返回的则是该方法返回的值 。
2、Dart 的作用域
Dart 没有 「public」「private」等关键字,默认就是公开的,私有变量使用 下划线 _开头。
3、Dart 是不是单线程模型?是如何运行的?
Dart 是单线程模型,如何运行的看这张图:
引用《Flutter中文网》里的话:
Dart 在单线程中是以消息循环机制来运行的,其中包含两个任务队列,一个是“微任务队列” microtask queue,另一个叫做“事件队列” event queue。
入口函数 main() 执行完后,消息循环机制便启动了。首先会按照先进先出的顺序逐个执行微任务队列中的任务,当所有微任务队列执行完后便开始执行事件队列中的任务,事件任务执行完毕后再去执行微任务,如此循环往复,生生不息。
4、 说一下 Future?
Future,字面意思「未来」,是用来处理异步的工具。
刚才也说过:
Dart 在单线程中是以消息循环机制来运行的,其中包含两个任务队列,一个是“微任务队列” microtask queue,另一个叫做“事件队列” event queue。
Future 默认情况下其实就是往「事件队列」里插入一个事件,当有空余时间的时候就去执行,当执行完毕后会回调 Future.then(v) 方法。
而我们也可以通过使用 Future.microtask 方法来向 「微任务队列」中插入一个任务,这样就会提高他执行的效率。
因为在 Dart 每一个 isolate 当中,执行优先级为 : Main > MicroTask > EventQueue
5、说一下 Stream?
Stream 和 Feature 一样,都是用来处理异步的工具。
但是 Stream 和 Feature 不同的地方是 Stream 可以接收多个异步结果,而Feature 只有一个。
Stream 的创建可以使用 Stream.fromFuture,也可以使用 StreamController 来创建和控制。
还有一个注意点是:普通的 Stream 只可以有一个订阅者,如果想要多订阅的话,要使用 asBroadcastStream()。
6、说一下 mixin?
首先mixin是一个定义类的关键字。直译出来是混入,混合的意思 Dart为了支持多重继承,引入了mixin关键字,它最大的特殊处在于: mixin定义的类不能有构造方法,这样可以避免继承多个类而产生的父类构造方法冲突。
7、StatefulWidget 的生命周期
initState():Widget 初始化当前 State,在当前方法中是不能获取到 Context 的,如想获取,可以试试 Future.delayed()
didChangeDependencies():在 initState() 后调用,State对象依赖关系发生变化的时候也会调用。
deactivate():当 State 被暂时从视图树中移除时会调用这个方法,页面切换时也会调用该方法,和Android里的 onPause 差不多。
dispose():Widget 销毁时调用。
didUpdateWidget:Widget 状态发生变化的时候调用。
8、 Flutter 如何与 Android iOS 通信?
Flutter 通过 PlatformChannel 与原生进行交互,其中 PlatformChannel 分为三种:
BasicMessageChannel:用于传递字符串和半结构化的信息。
MethodChannel:用于传递方法调用。Flutter主动调用Native的方法,并获取相应的返回值。
EventChannel:用于数据流(event streams)的通信。
9、dart是什么,和flutter有什么关系?
dart是一种面向对象语言,dart是flutter的程序开发语言。
10、main()和runApp()函数在flutter的作用分别是什么?有什么关系吗?
main函数是类似于java语言的程序运行入口函数
runApp函数是渲染根widget树的函数
一般情况下runApp函数会在main函数里执行
11、什么是widget? 在flutter里有几种类型的widget?分别有什么区别?能分别说一下生命周期吗?
widget在flutter里基本是一些UI组件有两种类型的widget,分别是statefulWidget 和 statelessWidget两种,statelessWidget不会自己重新构建自己,但是statefulWidget会
12、Hot Restart 和 Hot Reload 有什么区别吗?
Hot Reload比Hot Restart快,Hot Reload会编译我们文件里新加的代码并发送给dart虚拟机,dart会更新widgets来改变UI,而Hot Restart会让dart 虚拟机重新编译应用。另一方面也是因为这样, Hot Reload会保留之前的state,而Hot Restart回你重置所有的state回到初始值。
13、在flutter里streams是什么?有几种streams?有什么场景用到它?
Stream 用来处理连续的异步操作,Stream 是一个抽象类,用于表示一序列异步数据的源。它是一种产生连续事件的方式,可以生成数据事件或者错误事件,以及流结束时的完成事件
Stream 分单订阅流和广播流。
网络状态的监控
14、简单说一下在flutter里async和await?
await的出现会把await之前和之后的代码分为两部分,await并不像字面意思所表示的程序运行到这里就阻塞了,而是立刻结束当前函数的执行并返回一个Future,函数内剩余代码通过调度异步执行。
async是和await搭配使用的,await只在async函数中出现。在async 函数里可以没有await或者有多个await。
15、future 和steam有什么不一样?
在 Flutter 中有两种处理异步操作的方式 Future 和 Stream,Future 用于处理单个异步操作,Stream 用来处理连续的异步操作。
16、什么是flutter里的key? 有什么用?
key是Widgets,Elements和SemanticsNodes的标识符。
key有LocalKey 和 GlobalKey两种。
LocalKey 如果要修改集合中的控件的顺序或数量。GlobalKey允许 Widget 在应用中的任何位置更改父级而不会丢失 State。
17、在什么场景下使用profile mode?
profile model 是用来评估app性能的,profile model 和release mode是相似的,只有保留了一些需要评估app性能的debug功能。在模拟器上profile model是不可用的。
18、怎么做到只在debug mode运行代码?
foundation有一个静态的变量kReleaseMode来表示是否是release mode。
19、怎么理解Isolate?
isolate是Dart对actor并发模式的实现。 isolate是有自己的内存和单线程控制的运行实体。isolate本身的意思是“隔离”,因为isolate之间的内存在逻辑上是隔离的。isolate中的代码是按顺序执行的,任何Dart程序的并发都是运行多个isolate的结果。因为Dart没有共享内存的并发,没有竞争的可能性所以不需要锁,也就不用担心死锁的问题。
20、await for 如何使用?
await for是不断获取stream流中的数据,然后执行循环体中的操作。它一般用在直到stream什么时候完成,并且必须等待传递完成之后才能使用,不然就会一直阻塞。
21、请简单介绍下Flutter框架,以及它的优缺点?
Flutter是Google推出的一套开源跨平台UI框架,可以快速地在Android、iOS和Web平台上构建高质量的原生用户界面。同时,Flutter还是Google新研发的Fuchsia操作系统的默认开发套件。在全世界,Flutter正在被越来越多的开发者和组织使用,并且Flutter是完全免费、开源的。Flutter采用现代响应式框架构建,其中心思想是使用组件来构建应用的UI。当组件的状态发生改变时,组件会重构它的描述,Flutter会对比之前的描述,以确定底层渲染树从当前状态转换到下一个状态所需要的最小更改。
优点
热重载(Hot Reload),利用Android Studio直接一个ctrl+s就可以保存并重载,模拟器立马就可以看见效果,相比原生冗长的编译过程强很多;
一切皆为Widget的理念,对于Flutter来说,手机应用里的所有东西都是Widget,通过可组合的空间集合、丰富的动画库以及分层课扩展的架构实现了富有感染力的灵活界面设计;
借助可移植的GPU加速的渲染引擎以及高性能本地代码运行时以达到跨平台设备的高质量用户体验。简单来说就是:最终结果就是利用Flutter构建的应用在运行效率上会和原生应用差不多。
缺点
不支持热更新;
三方库有限,需要自己造轮子;
Dart语言编写,增加了学习难度,并且学习了Dart之后无其他用处,相比JS和Java来说。
22、介绍下Flutter的理念架构
由上图可知,Flutter框架自下而上分为Embedder、Engine和Framework三层。其中,Embedder是操作系统适配层,实现了渲染 Surface设置,线程设置,以及平台插件等平台相关特性的适配;Engine层负责图形绘制、文字排版和提供Dart运行时,Engine层具有独立虚拟机,正是由于它的存在,Flutter程序才能运行在不同的平台上,实现跨平台运行;Framework层则是使用Dart编写的一套基础视图库,包含了动画、图形绘制和手势识别等功能,是使用频率最高的一层。
23、介绍下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小很多。
*24、介绍下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。
*25、简述Widgets、RenderObjects 和 Elements的关系
首先看一下这几个对象的含义及作用。
Widget :仅用于存储渲染所需要的信息。
RenderObject :负责管理布局、绘制等操作。
Element :才是这颗巨大的控件树上的实体。
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 不会被重建,只是更新而已。
26、简述Flutter的绘制流程
Flutter只关心向 GPU提供视图数据,GPU的 VSync信号同步到 UI线程,UI线程使用 Dart来构建抽象的视图结构,这份数据结构在 GPU线程进行图层合成,视图数据提供给 Skia引擎渲染为 GPU数据,这些数据通过 OpenGL或者 Vulkan提供给 GPU。
27、Dart中var与dynamic的区别
使用var来声明变量,dart会在编译阶段自动推导出类型。而dynamic不在编译期间做类型检查而是在运行期间做类型校验。
28、const和final的区别
const 的值在编译期确定,final 的值在运⾏时确定。
29、Dart中??与??=的区别
两者都是dart中的操作符,??表示如果为空则返回,??=表示如果为空则赋值。
*30、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 不会被重建,只是更新而已。
31、Flutter在Debug和Release下分别使用什么编译模式,有什么区别?
Debug模式下使用JIT编译模式,即Just in time(即时编译),Release下使用AOT模式,即Ahead of time(提前编译)。JIT模式因为需要边运行边编译,所以会占用运行时内存,导致卡顿现象,但是有动态编译效果对于开发者来说非常方便调试。AOT模式提前编译不会占用运行时内存,相对来说运行流畅,但是会导致编译时间增加。
32、Flutter 是什么?
Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面。 Flutter可以与现有的代码一起工作。在全世界,Flutter正在被越来越多的开发者和组织使用,并且Flutter是完全免费、开源的。
33、Flutter 特性有哪些?
快速开发(毫秒级热重载)
绚丽UI(内建漂亮的质感设计Material Design和Cupertino Widget和丰富平滑的动画效果和平台感知)
响应式(Reactive,用强大而灵活的API解决2D、动画、手势、效果等难题)
原生访问功能
堪比原生性能
34、Flutter 和 Dart的关系是什么?
Flutter是一个使用Dart语言开发的跨平台移动UI框架,通过自建绘制引擎,能高性能、高保真地进行移动开发。Dart囊括了多数编程语言的优点,它更符合Flutter构建界面的方式。
35、dart的一些重要概念?
在Dart中,一切都是对象,所有的对象都是继承自Object
Dart是强类型语言,但可以用var或 dynamic来声明一个变量,Dart会自动推断其数据类型,dynamic类似c#
没有赋初值的变量都会有默认值null
Dart支持顶层方法,如main方法,可以在方法内部创建方法
Dart支持顶层变量,也支持类变量或对象变量
Dart没有public protected private等关键字,如果某个变量以下划线(_)开头,代表这个变量在库中是私有的
36、dart是值传递还是引用传递?
dart中,基本数据类型传值,类传引用。
37、 mixin extends implement 之间的关系?
继承(关键字 extends)、混入 mixins (关键字 with)、接口实现(关键字 implements)。这三者可以同时存在,前后顺序是extends -> mixins -> implements。
Flutter中的继承是单继承,子类重写超类的方法要用@Override,子类调用超类的方法要用super。
在Flutter中,Mixins是一种在多个类层次结构中复用类代码的方法。mixins的对象是类,mixins绝不是继承,也不是接口,而是一种全新的特性,可以mixins多个类,mixins的使用需要满足一定条件。
38、Flutter main future mirotask 的执行顺序?
普通代码都是同步执行的,结束后会开始检查microtask中是否有任务,若有则执行,执行完继续检查microtask,直到microtask列队为空。最后会去执行event队列(future)。
39、Future和Isolate有什么区别?
future是异步编程,调用本身立即返回,并在稍后的某个时候执行完成时再获得返回结果。在普通代码中可以使用await 等待一个异步调用结束。
isolate是并发编程,Dartm有并发时的共享状态,所有Dart代码都在isolate中运行,包括最初的main()。每个isolate都有它自己的堆内存,意味着其中所有内存数据,包括全局数据,都仅对该isolate可见,它们之间的通信只能通过传递消息的机制完成,消息则通过端口(port)收发。isolate只是一个概念,具体取决于如何实现,比如在Dart VM中一个isolate可能会是一个线程,在Web中可能会是一个Web Worker。
40、Stream 两种订阅模式?
Stream有两种订阅模式:单订阅(single) 和 多订阅(broadcast)。单订阅就是只能有一个订阅者,而广播是可以有多个订阅者。这就有点类似于消息服务(Message Service)的处理模式。单订阅类似于点对点,在订阅者出现之前会持有数据,在订阅者出现之后就才转交给它。而广播类似于发布订阅模式,可以同时有多个订阅者,当有数据时就会传递给所有的订阅者,而不管当前是否已有订阅者存在。
Stream 默认处于单订阅模式,所以同一个 stream 上的 listen 和其它大多数方法只能调用一次,调用第二次就会报错。但 Stream 可以通过 transform() 方法(返回另一个 Stream)进行连续调用。通过 Stream.asBroadcastStream() 可以将一个单订阅模式的 Stream 转换成一个多订阅模式的 Stream,isBroadcast 属性可以判断当前 Stream 所处的模式。
41、Flutter state生命周期方法之didChangeDependencies 、didUpdateWidget
didChangeDependencies
widget树中,若节点的父级结构中的层级 或 父级结构中的任一节点的widget类型有变化,节点会调用didChangeDependencies;若仅仅是父级结构某一节点的widget的某些属性值变化,节点不会调用didChangeDependencies
didUpdateWidget
widget树中,若节点调用setState方法,节点本身不会触发didUpdateWidget,此节点的子节点 会 调用didUpdateWidget
42、flutter key的种类
GlobalKey
Globalkey可以主动获取以及主动改变子控件的状态。
LocalKey
ValueKey
ObjectKey
UniqueKey
————————————————
版权声明:本文为CSDN博主「后山的猫咪」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41326577/article/details/124868251