1、Dart是什么? 和Flutter是什么关系?
Dart是Google开发的一种面向对象的计算机编程语言,和Java类似
Flutter 是 Google 开源的 UI 工具包,帮助开发者通过一套代码库高效构建多平台精美应用,支持移动、Web、桌面和嵌入式平台
Dart是flutter的程序开发语言
2. main()和runApp()函数在flutter的作用分别是什么?有什么关系吗?
main函数是类似于java语言的程序运行入口函数
runApp函数是渲染根widget树的函数
一般情况下runApp函数会在main函数里执行
3. 什么是widget? 在flutter里有几种类型的widget?分别有什么区别?能分别说一下生命周期吗?
Widget在flutter里基本是一些UI组件,和
在 Flutter 中,有两类常用的 Widget:
- 无状态的 StatelessWidget
- 有状态的 StatefulWidget
在开发过程中,我们经常需要继承它们两来实现自己的 Widget。
A、无状态的StatelessWidget
如果你的控件一旦显示,就不需要再做任何的变更,那么你应该使用 StatelessWidget。
实现一个自己的 StatelessWidget 很简单。
当你看到下面这个例子🌰时,你就知道它有多简单了。
class PageWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return _buildBody(context);
}
Widget _buildBody(BuildContext context){
return Container(
…
);
}
B、有状态的StatefulWidget
它可以改变界面的状态,比如显示的文字Text
、选中状态CheckBox
Switch
等
我们之所以可以改变状态是因为setState
,当调用setState
后,就会触发 StatefulWidget 的视图树重建。
setState((){
// 更新状态、数据
})
因此,当我们需要一个可交互的,即能根据用户操作或数据变化而改变视图的 Widget 时,那就得用上 StatefulWidget 了。
周期
State的生命周期和StatefulWidget不同,当StatefulWidget的状态改变之后就会被重建,但是State不会改变,但是 StatefulWidget在View树中移除再插入又会生成新的State.
总体介绍一下生命周期,大致可以看成三个阶段:
- 初始化 (插入渲染树🌲)
- 状态改变 (在渲染树中存在)
- 销毁 (从渲染树中移除)
生命周期详解
initState
当插入渲染树的时候调用,这个函数在生命周期中只调用一次. 这里可以做一些初始化的工作,比如初始化State的变量
didChangeDependencies
这个函数会紧跟在initState之后调用,并且可以调用BuildContext.inheritFromWidgetOfExactType, 那么BuildContext.inheritFromWidgetOfExactType的使用场景是什么呢?
static TabController of(BuildContext context) {
final _TabControllerScope scope = context.inheritFromWidgetOfExactType(_TabControllerScope);
return scope?.controller;
}
实际上就是调用BuildContext.inheritFromWidgetOfExactType,也就是说在didChangeDependencies中,可以跨组件拿到数据
didUpdateWidget
当组件的状态改变的时候就会调用didUpdateWidget, 比如调用setState,
实际flutter框架会创建一个新的Widget绑定State,并在函数中传递老的Widget.
这个函数一般用于比较新、老Widget,看看哪些属性改变了,并对State做一些调整.
需要注意的是涉及到controller的变更,需要在这个函数中移除老的controller的监听,并创建新controller.
deactivate
在dispoes之前,会调用这个函数
dispose
一旦到这个阶段,组件就会被销毁,这个函数一般会移除监听,清理环境
总结
阶段 | 调用次数 |
---|---|
构造函数 | 1 |
initState | 1 |
didChangeDependencies | >=1 |
didUpdateWidget | >=1 |
deactivate | >=1 |
dispose | 1 |
各方解释
- initState: 插入渲染树时调用只调用一次, widget创建执行的第一个方法, 可以再里面初始化一些数据,以及绑定控制器
- didChangeDependencies: 当State对象的依赖发生变化时被调用
- build: 它主要用户构建Widget字树的,调用次数:多次,初始化之后开始绘制界面,当调用setState触发的时候会再次被调用
- deactivate: 当State被暂时从视图树中移除时,会调用这个函数.
页面切换时也会调用它,因为此时State在视图树中的位置发送了变化,需要先暂时移除后添加 - dispose: 当State对象从树中被永久移除时调用; 通常在此回调中释放资源.
- reassemble: 此回调是为了专门开发调试而提供的,在热重载(hot reload)时会被调用, 此回调在Release模式下永远不会被调用
4. Hot Restart 和 Hot Reload 有什么区别吗?
Hot Reload比Hot Restart快,Hot Reload会编译我们文件里新加的代码并发送给dart虚拟机,dart会更新widgets来改变UI,而Hot Restart会让dart 虚拟机重新编译应用。另一方面也是因为这样, Hot Reload会保留之前的state,而Hot Restart回你重置所有的state回到初始值。
5. 在flutter里streams是什么?有几种streams?有什么场景用到它?
Stream 用来处理连续的异步操作,Stream 是一个抽象类,用于表示一序列异步数据的源。它是一种产生连续事件的方式,可以生成数据事件或者错误事件,以及流结束时的完成事件
Stream 分单订阅流和广播流。
网络状态的监控
6. 简单说一下在flutter里async和await?
await的出现会把await之前和之后的代码分为两部分,await并不像字面意思所表示的程序运行到这里就阻塞了,而是立刻结束当前函数的执行并返回一个Future,函数内剩余代码通过调度异步执行。
async是和await搭配使用的,await只在async函数中出现。在async 函数里可以没有await或者有多个await。
7. future 和steam有什么不一样?
Dart异步编程的两个特性
Future
和Stream
在 Flutter 中有两种处理异步操作的方式 Future 和 Stream,Future 用于处理单个异步操作,Stream 用来处理连续的异步操作.
-
Stream
a、Stream 就是事件流或者管道,是一些的异步
事件,它会在上一个事件完成时通知你进行下一个事件.
b、Stream无论用什么方式创建,都会以相同的方式返回并使用: asynchronous for loop(await for)
. 例子🌰:
Future<int> sumStream(Stream<int> stream) async {
var sum = 0;
await for (var value int stream) {
sum += value;
}
return sum;
}
c、Stream 提供 asynchronous序列化的数据.
d、该序列化数据包含了用户生成的时间和重文件中读取的数据.
e、你可以通过await for 的listen()
来处理Stream API返回的数据流.
f、Stream 提供了错误相应的处理方法.
g、Streams 有两种方式:single subscription
(订阅) 和 broadcast
(广播), 下面是两种Streams类型说明:
1、Single subscription streams (单一订阅)
- 最常见,最基本的streams实现方式
- 它的数据大部分是sequence of events. 单一订阅必须以正确的顺序交付事件,并且中间不能有任何异常
- 这是当你在读取文件或者接受网络请求的时候产生的stream.
- 这样的流不具备幂等性,再次接收可能会不同于上次的请求
- 当你开始监听, 数据将被提取并以块的形式提供
2、Broadcast streams (广播)
- 适用于可以一次处理一个的单个消息, 例如:这种流可用于浏览器中的鼠标事件.
- 可以随时监听开始监听这样的流, 并且再收听时会触发事件
- 多个收听者可以同时收听, 也可以取消上一个订阅后再次收听
-
Future
8. 什么是flutter里的key? 有什么用?
key是Widgets,Elements和SemanticsNodes的标识符。
key有LocalKey 和 GlobalKey两种。
LocalKey 如果要修改集合中的控件的顺序或数量。GlobalKey允许 Widget 在应用中的任何位置更改父级而不会丢失 State。
9. 在什么场景下使用profile mode?
profile model 是用来评估app性能的,profile model 和release mode是相似的,只有保留了一些需要评估app性能的debug功能。在模拟器上profile model是不可用的。
10. 怎么做到只在debug mode运行代码?
foundation有一个静态的变量kReleaseMode来表示是否是release mode
11. 怎么理解Isolate?
isolate是Dart对actor并发模式的实现。 isolate是有自己的内存和单线程控制的运行实体。isolate本身的意思是“隔离”,因为isolate之间的内存在逻辑上是隔离的。isolate中的代码是按顺序执行的,任何Dart程序的并发都是运行多个isolate的结果。因为Dart没有共享内存的并发,没有竞争的可能性所以不需要锁,也就不用担心死锁的问题
12. 列举在flutter的状态管理方案?
-
Scoped Model
-
Redux
-
BLoC
-
RxDart
-
provider