来自某校试题,最完整题所以前面的最完整题会比较简单,后面的最完整题会比较难,主要想测出学生的最完整题真实水平,只是最完整题部分,一共153题;
A、最完整题Container B、最完整题Center C、最完整题Align D、最完整题Card
A、最完整题expands B、最完整题maxLength C、最完整题textAlign D、最完整题maxLines
A、最完整题fit: BoxFit.fill B、最完整题fit: BoxFit.cover C、repeat: ImageRepeat.repeat
A、data B、style C、overflow D、maxLines
A、Card B、Center C、Offstage D、Visibility
A、在树中的给定位置为此小部件创建可变状态;
B、框架可以在整个生命周期中多次调用此方法;
C、如果将小部件从树中删除,并且稍后再次插入树中,框架将调用再次创建一个新的对象,从而简化了State对象;
D、用来看的,没啥实际作用;
A、在点击某按钮时触发进行刷新类实例变量;
B、在点击某按钮时触发进行刷新方法实例变量;
C、使用前先判断是否为;
D、生命周期中调用;
A、属性设置为;
B、组件包裹;
C、设置为;
D、设置为;
A、一片红的报错信息;
B、报错,但不影响布局;
C、不会报错;
D、因为是的调用,左边为空了则不会去调用播放方法;
A、一片红的报错信息;
B、报错,但不影响布局;
C、不会报错;
D、会报生命周期创建错误;
A、可能是外层写了间隔之类的;
B、可能是自带;
C、肯定是官方的问题;
D、人的问题,换个人来运行可能就好了;
A、ListView B、GridView C、Container D、Center
A、SliverToBoxAdapter
B、SliverAppBar
C、SliverAnimatedOpacity
D、Image
A、Text B、SingleChildScrollView C、Card D、FlatButton
A、FlatButton B、RaisedButton C、Align D、Container
A、使用来指定当左边为空时才执行等于;
B、使用三元运算符判断是否等于空才执行赋值;
C、使用判断语句,为空时才等于;
D、直接使用等于来赋值;
A、全局设置水波纹颜色为透明;
B、局部设置水波纹颜色为透明然后包裹需要透明的组件;
C、使用按钮的水波纹颜色属性设置为透明;
D、发呆就对了,阿巴阿吧阿吧;
A、用手写代码的情况下;
B、在不摸鱼的情况下;
C、混入必须是继承的情况下;
D、具备有状态类的生命周期下;
A、每个平台都有判断,效果会出现不同点;
B、Android和IOS怎么滑效果都一样;
C、Android滑动到无法滑动之后会出现焦点特殊动画,而IOS是回弹效果;
D、我又没滑过,我懒个晓得咯;
A、以约束盒子的为准;
B、以内部设置的为准;
C、会造成混乱,导致无法显示;
D、有时候会,有时候会;
1、表示:AA如果为空,则显示999
2、表示:AA如果为空,则给值设置为999
3、表示:AA对于999整除
4、表示:A如果为空则不调用,如果不为空则调用a值
5、表示:A如果为空则不调用,如果不为空则调用a值,然后a值为空则显示999
优点:1、高性能,2、高保真,3、相对易学,4、热重载;
缺点:1、不支持热更新,2、生态需完善;
自写UI渲染引擎实现跨平台
1、web技术,2、原生渲染,3、自渲染技术;
A:
触发代码:
使用调用到的方法;
1.被约束了;2.宽高无限了;
使用包裹容器;
1.溢出部分增加滑动属性;2.的让其遮挡布局;
原因: 设置 只对当前盒子生效;
解决方式:使用裁剪方式,如:组件;
使用的
1.控制器重新赋值;(使用不能是的)
2.使用;
有可能使用了单一的Ticker(),只能使用一次就失效了;
属性让其遮挡布局;
可能是输入中没有做保存处理,可以使用生命周期判断,在程序暂停前让输入框取消焦点即可实现自动保存;
原因:切换之后才开始解析本地资源图片;
解决方案:在初始化的时候就加载指定asset图片,而不是在需要展示的时候才开始加载。
代码示例:
组件,用返回的来操作是否允许返回;
使用观察生命周期状态;
具体:book.flutterj.com/chapter1/li…
让组件的所占宽度可知;
1、使用拿到上下文取得拿内容的尺寸数据;
2、使用取得拿内容的尺寸数据;
调用父类的属性,可进行赋值传输;
assert:断言;
:data不能为空,否则触发断言错误;
no data:如果触发断言则提示的内容;
构造函数前:构造函数会在编译期和常量一起被编译;
声明数值前:一个不可变的常量,编译期就被初始化;
Dart 中所有的基础类型、类等都继承 ,默认值是 , 自带 和 ,而如果是 或者 的话,那么它只有一个 方法, 都支持 、 重写
在的时候提示出断言错误让开发者知悉,只在有效;
级连操作符
“..” 和 “.” 不同:调用后返回的相当于是,而返回的则是该方法返回的值;
Dart没有和等关键词,默认就是公开的,私有变量使用下划线开头;
单线程执行,多线程是使用异步来执行的;
阻塞:调用结果之前,当前线程会被挂起,调用线程只有在得到结果之后才会继续执行;
非阻塞:调用执行之后,当前线程不会停止运行,只需要过一段时间来检查有没有结果返回即可;
将需要处理的一系列事件,放在一个事件队列()中,不断从事件队列中取出事件,并执行需要执行的代码块,直到事件被清空。
dart是值传递。我们每次调用函数,传递过去的都是对象的内存地址,而不是这个对象的复制。
Productive(生产力高,Dart的语法清晰明了,工具简单但功能强大)
Fast(执行速度快,Dart提供提前优化编译,以在移动设备和Web上获得可预测的高性能和快速启动。)
Portable(易于移植,Dart可编译成ARM和X86代码,这样Dart移动应用程序可以在iOS、Android和其他地方运行)
Approachable(容易上手,充分吸收了高级语言特性,如果你已经知道C++,C语言,或者Java,你可以在短短几天内用Dart来开发)
Reactive(响应式编程)
在Dart中,一切都是对象,所有的对象都是继承自
Dart是强类型语言,但可以用var或 来声明一个变量,Dart会自动推断其数据类型,类似c#
没有赋初值的变量都会有默认值
Dart支持顶层方法,如方法,可以在方法内部创建方法
Dart支持顶层变量,也支持类变量或对象变量
Dart没有 等关键字,如果某个变量以下划线(_)开头,代表这个变量在库中是私有的
Dart 是单线程模型,运行的的流程如下图。
Dart 在单线程中是以消息循环机制来运行的,包含两个任务队列,一个是“微任务队列” ,另一个叫做“事件队列” 。当Flutter应用启动后,消息循环机制便启动了。首先会按照先进先出的顺序逐个执行微任务队列中的任务,当所有微任务队列执行完后便开始执行事件队列中的任务,事件任务执行完毕后再去执行微任务,如此循环往复,生生不息。
Dart 是单线程的,不存在多线程,那如何进行多任务并行的呢?其实,Dart的多线程和前端的多线程有很多的相似之处。Flutter的多线程主要依赖Dart的并发编程、异步和事件驱动机制。
简单的说,在Dart中,一个对象其实就是一个执行环境的引用,一般来说我们都是通过当前的去控制其他的完成彼此之间的交互,而当我们想要创建一个新的可以使用方法获取返回的一个新的对象,两个之间使用相互发送消息,而中也存在了一个与之对应的接受消息用来处理,但是我们需要注意的是,和在每个都有一对,只有同一个中的才能接受到当前类的发送的消息并且处理。
是不断获取流中的数据,然后执行循环体中的操作。它一般用在直到什么时候完成,并且必须等待传递完成之后才能使用,不然就会一直阻塞。
单订阅()和多订阅()。
单订阅就是只能有一个订阅者,而广播是可以有多个订阅者。这就有点类似于消息服务()的处理模式。单订阅类似于点对点,在订阅者出现之前会持有数据,在订阅者出现之后就才转交给它。而广播类似于发布订阅模式,可以同时有多个订阅者,当有数据时就会传递给所有的订阅者,而不管当前是否已有订阅者存在。 默认处于单订阅模式,所以同一个 上的 和其它大多数方法只能调用一次,调用第二次就会报错。但 可以通过 方法(返回另一个 )进行连续调用。通过 可以将一个单订阅模式的 转换成一个多订阅模式的 , 属性可以判断当前 所处的模式。
是Dart 2.1 加入的特性,以前版本通常使用代替。简单来说,是为了解决继承方面的问题而引入的机制,Dart为了支持多重继承,引入了关键字,它最大的特殊处在于:定义的类不能有构造方法,这样可以避免继承多个类而产生的父类构造方法冲突。的对象是类,绝不是继承,也不是接口,而是一种全新的特性,可以多个类,的使用需要满足一定条件。
借助于先进的工具链和编译器,Dart 是少数同时支持 JIT(Just In Time,即时编译)和 AOT(Ahead of Time,运行前编译)的语言之一。那,到底什么是 JIT 和 AOT 呢?语言在运行之前通常都需要编译,JIT 和 AOT 则是最常见的两种编译模式。JIT 在运行时即时编译,在开发周期中使用,可以动态下发和执行代码,开发测试效率高,但运行速度和执行性能则会因为运行时即时编译受到影响。AOT 即提前编译,可以生成被直接执行的二进制代码,运行速度快、执行性能表现好,但每次执行前都需要提前编译,开发测试效率低。
Dart VM 的内存分配策略比较简单,创建对象时只需要在堆上移动指针,内存增长始终是线性的,省去了查找可用内存的过程。在 Dart 中,并发是通过 实现的。 是类似于线程但不共享内存,独立运行的 。这样的机制,就可以让 Dart 实现无锁的快速分配。Dart 的垃圾回收,则是采用了多生代算法。新生代在回收内存时采用“半空间”机制,触发垃圾回收时,Dart 会将当前半空间中的“活跃”对象拷贝到备用空间,然后整体释放当前空间的所有内存。回收过程中,Dart 只需要操作少量的“活跃”对象,没有引用的大量“死亡”对象则被忽略,这样的回收机制很适合 Flutter 框架中大量 Widget 销毁重建的场景。
因为使用的条件,随着Dart版本一直在变,这里讲的是Dart2.1中使用的条件:
类只能继承自类不能有构造函数
一个类可以多个类
可以多个类,不破坏Flutter的单继承
关键字可用于指定异常类型。 只能用于被标记的类,例如,意思是要的话,得先接口实现或者继承。这里可以是类,也可以是接口,但是在的时候用法有区别.
一个类:
的是一个接口: 得首先实现这个接口,然后再用
普通代码都是同步执行的,结束后会开始检查中是否有任务,若有则执行,执行完继续检查,直到列队为空。最后会去执行队列()。
是异步编程,调用本身立即返回,并在稍后的某个时候执行完成时再获得返回结果。在普通代码中可以使用 等待一个异步调用结束。是并发编程,Dart有并发时的共享状态,所有Dart代码都在中运行,包括最初的。每个都有它自己的堆内存,意味着其中所有内存数据,包括全局数据,都仅对该可见,它们之间的通信只能通过传递消息的机制完成,消息则通过端口()收发。只是一个概念,具体取决于如何实现,比如在中一个可能会是一个线程,在Web中可能会是一个。
和 是 Dart 异步处理的核心 API。 表示稍后获得的一个数据,所有异步的操作的返回值都用 来表示。但是 只能表示一次异步获得的数据。而 表示多次异步获得的数据。比如界面上的按钮可能会被用户点击多次,所以按钮上的点击事件()就是一个 。简单地说,将返回一个值,而将返回多次值。Dart 中统一使用 处理异步事件流。 和一般的集合类似,都是一组数据,只不过一个是异步推送,一个是同步拉取。
Flutter的层是用Dart编写的框架(SDK),它实现了一套基础库,包含(Android风格UI)和(iOS风格)的UI界面,下面是通用的(组件),之后是一些动画、绘制、渲染、手势库等。这个纯 Dart实现的 SDK被封装为了一个叫作 的 Dart库。我们在使用 Flutter写 App的时候,直接导入这个库即可使用组件等功能。Flutter的层是的绘图引擎库,其前身是一个向量绘图软件,Chrome和 Android均采用 作为绘图引擎。Skia提供了非常友好的 API,并且在图形转换、文字渲染、位图渲染方面都提供了友好、高效的表现。Skia是跨平台的,所以可以被嵌入到 Flutter的 iOS SDK中,而不用去研究 iOS闭源的 。Android自带了 ,所以 Flutter Android SDK要比 iOS SDK小很多。
Flutter的分为和两种。其中,是无状态的,是有状态的,因此实际使用时,更多的是。的生命周期如下图
首先看一下这几个对象的含义及作用。
会被到,并由管理底层渲染树。并不会直接管理状态及渲染,而是通过这个对象来管理状态。Flutter创建的可见树,相对于来说,是可变的,通常界面开发中,我们不用直接操作,而是由框架层实现内部逻辑。就如一个UI视图树中,可能包含有多个(被使用多次),但是放在内部视图树的视角,这些都是填充到一个个独立的中。会持有和的实例。记住, 只是一个配置, 负责管理布局、绘制等操作。在第一次创建 的时候,会对应创建一个 , 然后将该元素插入树中。如果之后 发生了变化,则将其与旧的 进行比较,并且相应地更新 。重要的是, 不会被重建,只是更新而已。
Flutter 通过 与原生进行交互,其中 分为三种:
关于原理:www.jianshu.com/p/39575a90e…
Flutter 的热重载是基于 JIT 编译模式的代码增量同步。由于 JIT 属于动态编译,能够将 Dart 代码编译成生成中间代码,让 在运行时解释执行,因此可以通过动态更新中间代码实现增量同步。
热重载的流程可以分为 5 步,包括:扫描工程改动、增量编译、推送更新、代码合并、 重建。
Flutter 在接收到代码变更后,并不会让 App 重新启动执行,而只会触发 树的重新绘制,因此可以保持改动前的状态,大大缩短了从代码修改到看到修改产生的变化之间所需要的时间。
另一方面,由于涉及到状态的保存与恢复,涉及状态兼容与状态初始化的场景,热重载是无法支持的,如改动前后 状态无法兼容、全局变量与静态属性的更改、 方法里的更改、 方法里的更改、枚举和泛型的更改等。
可以发现,热重载提高了调试 UI 的效率,非常适合写界面样式这样需要反复查看修改效果的场景。但由于其状态保存的机制所限,热重载本身也有一些无法支持的边界。
React Native 之类的框架,只是通过 JavaScript 虚拟机扩展调用系统组件,由 Android 和 iOS 系统进行组件的渲染;
Flutter 则是自己完成了组件渲染的闭环。那么,Flutter 是怎么完成组件渲染的呢?这需要从图像显示的基本原理说起。在计算机系统中,图像的显示需要 CPU、GPU 和显示器一起配合完成:CPU 负责图像数据计算,GPU 负责图像数据渲染,而显示器则负责最终图像显示。CPU 把计算好的、需要显示的内容交给 GPU,由 GPU 完成渲染后放入帧缓冲区,随后视频控制器根据垂直同步信号(VSync)以每秒 60 次的速度,从帧缓冲区读取帧数据交由显示器完成图像显示。操作系统在呈现图像时遵循了这种机制,而 Flutter 作为跨平台开发框架也采用了这种底层方案。下面有一张更为详尽的示意图来解释 Flutter 的绘制原理。
Flutter 绘制原理可以看到,Flutter 关注如何尽可能快地在两个硬件时钟的 信号之间计算并合成视图数据,然后通过 交给 GPU 渲染:UI 线程使用 Dart 来构建视图结构数据,这些数据会在 GPU 线程进行图层合成,随后交给 引擎加工成 GPU 数据,而这些数据会通过 最终提供给 GPU 渲染。
在flutter中,每个都是被唯一标识的。这个唯一标识在或g阶段由框架定义。该标识对应于可选的参数,如果省略,Flutter将会自动生成一个。
在flutter中,主要有4种类型的:(确保生成的Key在整个应用中唯一,是很昂贵的,允许在树周围移动或变更父节点而不会丢失状态)、、、。
是在Flutter中负责管理维护页面堆栈的导航器。
在需要的时候,会自动为我们创建。
,会使用来向上遍历树,找到提供的再调用其方法完成导航操作。
在应用使用过程中常见动画模式:
A:
A:
在方法修改 来自定义一个属于自己的;
如:
Flutter 中存在四大线程,分别为 、、, (原生主线程) ,同时在 Flutter 中可以通过 或者 执行真正的跨线程异步操作。
Flutter 中通过 可以嵌套原生 到 中;
、 、 等;
使用了类似副屏显示的技术, 类代表一个虚拟显示器,调用 的 方法,将虚拟显示器的内容渲染在一个 控件上,然后将 的 通知给 Dart,让 绘制时,在内存中找到对应的 画面内存数据,然后绘制出来。 实时控件截图渲染显示技术。
Flutter 的 下是 模式,下是模式。
->->->, 但是用户一般不会直接调用 ,而是通过 ,具体流程如下:
在 之后会通过 使得页面重绘,流程大概如下:
通过 往上确定了更新区域,通过 方法触发更新往下绘制。
Flutter 中存在 、 、 、 四棵树,其中 与 是一对多的关系 ,
默认情况下,层会创建一个,并且Dart代码默认就运行在这个主上。必要时可以使用和两种方式来创建新的,在Flutter中,新创建的由Flutter进行统一的管理。事实上,自己不创建和管理线程,线程的创建和管理是负责的,指的是将引擎移植到平台的中间层代码,层的架构示意图如下图所示。
在Flutter的架构中,提供四个,分别是、、和,每个负责不同的任务,不在乎运行在哪个线程,但是它需要线程在整个生命周期里面保持稳定
程序=算法+数据结构 数据是程序的中心。数据结构和算法两个概念间的逻辑关系贯穿了整个程序世界,首先二者表现为不可分割的关系。其实Flutter不就是一个程序吗,那我们面临的最底层的问题还是算法和数据结构,所以我们推导出
Flutter=算法+数据结构 那状态管理是什么?我也用公式来表达一下,如下:
Flutter状态管理=算法+数据结构+UI绑定
用于解决状态更新问题,不需要 被全局化,保证组件隐私,使得代码可扩展,易维护,可以动态替换UI而不影响算法逻辑,安全可靠,保持数据的稳定伸缩,性能佳,局部优化;
分为局部管理和全局管理;
局部管理优于全局、保持数据安全性、考虑页面重新带来的影响;
增加代码复杂性、框架bug修复需要时间等待、不理解框架原理导致使用方式不对,反而带来更多问题、选型错误导致不符合应用要求、与团队风格冲突不适用;
其实是调用了 ,该方法内部标记此 为 ,然后在下一帧 才会被绘制, 并不是立即生效的。
Flutter 中 启动入口其实是一个 ,它主要是通过 的子类 、 、 、 、 、 、 等,通过 的组合而成的。
Dart虚拟机拥有自己的,完全由虚拟机自己管理的,Flutter引擎也无法直接访问。Dart的UI相关操作,是由通过Dart的C++调用,或者是发送消息通知的方式,将UI渲染相关的任务提交到执行,这样就可以跟Flutter引擎相关模块进行交互。
1、同一个线程在同一时间只能进入一个,当需要进入另一个则必须先退出当前的;
2、一次只能有一个线程关联对应的,线程是执行Dart代码并使用虚拟机的公共的C语言API的线程;
是一个辅助类,其核心工作就是,将dart转为二进制,然后可直接使用二进制运行在主里面运行。
A:
A:
A:
A:
1、刷新方法内声明的变量;
2、刷新被修饰的变量;
线程之间的通信主要通过来进行,这个消息传递过程是异步的。
实例化一个的过程包括:
1.源码或者二进制()
2.snapshot :
将dart代码转换为二进制和执行二进制,这两个过程也可以分离开来,在两个不同的机器执行,比如机器执行编译,移动设备执行文件。
这个编译过程并不是自身完成,而是交给另一个进程来执行,它包括和一些专有的转换器。:热重载机制正是依赖这一点,重用上一次编译中的状态,只重新编译实际更改的部分。
部分还在更新中,任何问题可以加入我们的Flutter微信交流群,加好友即可拉群;
Flutter交流QQ群:874592746