热点新闻
flutter面试题
2023-07-28 17:57  浏览:2558  搜索引擎搜索“混灰机械网”
温馨提示:信息一旦丢失不一定找得到,请务必收藏信息以备急用!本站所有信息均是注册会员发布如遇到侵权请联系文章中的联系方式或客服删除!
联系我时,请说明是在混灰机械网看到的信息,谢谢。
展会发布 发布信息 广告合作 软文发布

一、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 > dispose 6、dispose 调用次数:1次 当State对象从树中被永久移除时调用;通常在此回调中释放资源。 7、reassemble 在热重载(hot reload)时会被调用,此回调在Release模式下永远不会被调用

原文链接:https://blog.csdn.net/yoonerloop/article/details/121003373

1.WidgetsBindingObserver

和App生命周期有关AppLifecycleState

1、resumed 可见并能响应用户的输入,同安卓的onResume 2、inactive 处在并不活动状态,无法处理用户响应,同安卓的onPause 3、paused 不可见并不能响应用户的输入,但是在后台继续活动中,同安卓的onStop 下面是生命周期: 初次打开widget时,不执行AppLifecycleState的回调; 按home键或Power键, AppLifecycleState inactive---->AppLifecycleState pause 从后台到前台:AppLifecycleState inactive--->ApplifecycleState resumed back键退出应用: AppLifecycleState inactive--->AppLifecycleState paused

原文链接:https://blog.csdn.net/yoonerloop/article/details/121003373</blockcode>

//初始化一些变量 void onCreate() {} //onResume 只要页面切换到栈顶,都会调用此方法 void onResume() { _isResume = true; _isPause = false; } //页面被覆盖,暂停 void onPause() { _isResume = false; _isPause = true; } void onDestroy() {}</blockcode>

LifeCycleInnerState

2.RouteAware

监听路由变化

RouteObserver 是一个配合RouteAware的一个类,通过这个类可以通知到当前页面应该执行那种生命周期方法,否则只混入RouteAware是不能执行的。另外还有RouteObserver需要注册在MaterialApp中,这样才能在导航的过程中执行到对应的生命周期方法。navigatorObservers

@override void didPush() { super.didPush(); //从其他页面跳转到当前页面 log("didPush"); _isTop = true; } @override void didPushNext() { //从当前页面跳转到下一页之后才会调用? super.didPushNext(); log("didPushNext"); onPause(); //在本页面执行onPause() _isTop = false; } @override void didPop() { //从当前页面退回当上一页面 super.didPop(); //pop onPause();//在当前页执行onPause() } @override void didPopNext() { super.didPopNext();//从其他页面Pop之后,进入到当前页面 onResume();//在当前页面执行onResume() _isTop = true; }

原文链接:https://blog.csdn.net/happiness365/article/details/122782217</blockcode>

三、flutter树结构

Widget树、Element树、RenderObject树

并不是所有的Widget都会被独立渲染!只有继承RenderObjectWidget的才会创建RenderObject对象

每一个Widget都会创建一个Element对象

隐式调用createElement方法。Element加入Element树种

它会创建三种Element

1.RenderElement主要是创建RenderObject对象 继承RenderObjectWidget的Widget会创建RenderElement 创建RanderElementFlutter会调用mount方法,调用createRanderObject方法 2.StatefulElement继承ComponentElement StatefulWidget会创建StatefulElement 调用createState方法,创建State将Widget赋值给state调用state的build方法 并且将自己(Element)传出去 build里面的context就是Widget的Element! 3.StatelessElement继承ComponentElement StatelessWidget会创建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()中传入命名参数onError async和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先进先出原则。通过拦截器你可以在请求之前、响应之后和发生异常时(但还没有被then或catchError处理)做一些统一的预处理操作。

链接:https://www.liujunmin.com/flutter/dio_analysis.html

发布人:e735****    IP:117.173.23.***     举报/删稿
展会推荐
让朕来说2句
评论
收藏
点赞
转发