一、Dart是单线程还是多线程?是如何运行的?
Dart本身是单线程模型。 在单线程中是以消息循环机制来运行的,其中包含两个任务队列,一个是“微任务队列” microtask queue 另一个是“事件队列” event queue。
主线程依赖事件循环持续处理任务,工作流程如下:
- 步骤1:执行
main()
函数中的同步代码。 - 步骤2:检查并执行 微任务队列(Microtask Queue) 中的所有任务,直到队列清空。
- 步骤3:处理 事件队列(Event Queue) 中的任务(如 I/O 回调、Timer、用户交互事件)。
- 步骤4:重复步骤2和步骤3,直到应用退出。
二、描述一下Flutter的三棵树。
-
Widget:不可变的UI配置(如
Text("Hello")
)。 -
Element:Widget的实例化对象,管理生命周期和树结构。
-
RenderObject:负责布局和绘制(如尺寸、位置计算)。
三、flutter有几种widget?
Flutter的Widget主要分为两种核心类型:
1. StatelessWidget(无状态组件)
- 不可变性:一旦创建后无法更改内部状态,所有属性均为
final
类型 - 构建特性:通过
build()
方法返回固定的UI结构,仅在初始化时构建一次 - 典型场景:静态显示内容(如纯文本、图标)、无需响应交互变化的UI元素
- 代码示例:
class MyText extends StatelessWidget {
final String title;
MyText(this.title); // 构造函数接收不可变参数
@override
Widget build(BuildContext context) {
return Text(title); // 返回固定结构的组件
}
}
2. StatefulWidget(有状态组件)
- 状态可变性:通过关联的
State
对象管理动态数据,可调用setState()
触发UI更新。 - 生命周期:包含
initState()
、dispose()
等生命周期方法,适合处理资源初始化和释放 - 典型场景:用户交互(如按钮点击)、数据实时更新(如计时器、表单输入)
- 代码示例:
class Counter extends StatefulWidget { @override _CounterState createState() => _CounterState(); // 创建对应的状态对象 } class _CounterState extends State<Counter> { int _count = 0; void _increment() { setState(() { // 触发UI重绘 _count++; }); } @override Widget build(BuildContext context) { return ElevatedButton( onPressed: _increment, child: Text('Count: $_count'), ); } }
四、说说几种常用的状态管理。它们之间有什么区别?
- Provider:基于
InheritedWidget
,轻量级,适合中小项目。 - Bloc:基于Stream和事件驱动,适合复杂状态逻辑。
- Riverpod:Provider的改进版,解决依赖注入问题。
- GetX:集成路由、依赖注入,API简洁。
五、说说几种平时常用的Key?
1. GlobalKey:
GlobalKey
是所有Key
类型中最常用的一个。它允许你访问widget的上下文,这对于需要直接与widget交互(例如获取或设置其状态)的情况非常有用。例如,当你需要在widget树之外访问某个特定widget的状态或调用其方法时,可以使用GlobalKey
。
2. LocalKey:
LocalKey
是Key
的基础类,通常用于不需要跨组件通信的简单场景。例如,当你仅仅需要保持某个widget的重建稳定性时,可以使用LocalKey
。
3. ValueKey:
ValueKey
是LocalKey
的一个具体实现,它接受一个值作为其参数,这个值必须是全局唯一的(即在应用的整个生命周期内唯一),以便于Flutter能够区分不同的widget实例。
4. ObjectKey:
ObjectKey
接受一个对象作为其参数,这个对象在整个应用生命周期内应该是唯一的。它通常用于当你想用某个对象的引用作为key时。
5. UniqueKey:
当你需要在运行时动态创建多个具有唯一标识的widget时,可以使用UniqueKey
。每次创建UniqueKey
实例时,它都会生成一个唯一的标识符。