咱们每一篇设计5个内容,这样能够快速掌握和巩固,后面我会出一个合集,用于大家综合复习。
一、Flutter中JIT和AOT的区别?
首先我们要知道JIT和AOT是什么?
JIT的全拼是Just-In-Time、AOT的全拼是Ahead-Of-Time。看完短语是不是已经可以理解一半了?
- 编译时机:
(1)AOT编译:在应用发布之前将Dart代码编译为机器码。这意味着应用在发布到设备前已经完全编译好。
(2)JIT编译:在应用运行时动态编译代码,将Dart代码编译为机器码。这意味着代码在执行之前是即时编译的。 - 性能和优化:
(1)AOT编译:适用于生产环境,能够生成优化后的应用程序,确保发布到生产环境时的高性能和低启动时间。AOT编译的所有代码一次性编译为机器码,运行时无需再进行编译,启动快,适用于资源受限场景如移动端和嵌入式设备。
(2)JIT编译:在开发模式下使用JIT编译可以实现热重载,让开发者快速查看代码更改后的效果。JIT编译具备运行时动态优化能力,如方法内联、逃逸分析等,能够根据实际执行情况做优化,但启动时慢,首次执行性能差。 - 开发效率和测试:
(1)AOT编译:虽然开发测试效率低,但能够生成直接执行的二进制代码,运行速度快,执行性能表现好。
(2)JIT编译:在开发时提供灵活性和动态优化,开发测试效率高,但运行速度和执行性能会受到即时编译的影响。
二、Flutter中热重载(Hot Reload)和热重启(Hot Restart),使用起来有什么区别(或者说区别是什么)。
1. 热重载(Hot Reload)主要用于在代码更改后立即看到效果,特别是在进行小范围修改时(如修改变量、添加打印语句等)。它几乎可以立即应用代码更改,并且通常不会丢失应用程序的状态。这对于开发调试阶段非常有用,它允许开发者快速迭代和测试。
2.热重启(Hot Restart)比热重载更彻底。会加载最新的代码,还会重启整个应用程序,这意味着所有的状态(例如用户界面上的输入和滚动位置)都会丢失。因此,如果更改依赖于应用程序的初始状态或者涉及到全局状态的重大更改,热重启可能是更好的选择。
三、描述一下Flutter的生命周期。
flutter生命周期的主要体现在两个方面:Widget的生命周期和State的生命周期。理解这两个概念对于构建稳定、高效的Flutter应用至关重要。
1. Widget的生命周期
Flutter的Widget生命周期主要由StatelessWidget
和StatefulWidget
的管理。
StatelessWidget
StatelessWidget
是不可变的,它的生命周期非常简单,主要包括:
-
创建:当Widget被创建时,它的
build
方法会被调用。 -
渲染:根据
build
方法返回的Widget树,Flutter框架渲染UI。 -
销毁:当Widget不再需要时(例如,当它从Widget树中移除时),它会被垃圾回收。
StatefulWidget
StatefulWidget
是可变的,它有一个与之关联的State
对象,其生命周期包括:
-
创建:当
StatefulWidget
被创建时,它的createState
方法被调用,创建一个新的State
对象。 -
初始化:
State
对象的initState
方法被调用,用于初始化状态。 -
渲染:根据
State
对象的build
方法返回的Widget树,Flutter框架渲染UI。 -
更新:当
State
对象需要更新时(例如,当其状态改变时),其build
方法会被重新调用,然后重新渲染UI。 -
销毁:当
StatefulWidget
从Widget树中移除时,其关联的State
对象的dispose
方法被调用,用于清理资源。
2. State的生命周期方法
在StatefulWidget
中,你可以重写几个重要的生命周期方法来自定义行为:
-
initState():在对象第一次创建后、渲染任何东西之前调用。通常用于初始化操作。
-
didChangeDependencies():当
State
对象的依赖发生变化时调用(例如,当继承自InheritedWidget
的依赖项发生变化时)。 -
build():这是最核心的方法,它应该描述如何构建widget的界面。Flutter框架会多次调用此方法以保持界面更新。
-
didUpdateWidget(oldWidget):当widget更新时调用,允许你在每次widget更新后执行一些操作。
-
deactivate():当widget被移除但仍保留在树中(例如,通过导航到另一个路由)时调用。
-
dispose():在对象被永久销毁之前调用。用于清理资源,例如取消订阅事件或释放资源。
四、Flutter中mixin、extends 和 implements三者的区别?
1. extends(继承)
定义:建立类之间的 is-a 关系,子类通过继承父类获得所有非私有属性和方法的实现,允许通过 @override 重写父类方法。
特点:
Dart 支持 单继承,一个类只能有一个直接父类;
子类自动继承父类已实现的功能,无需重新编写;
构造函数不能继承,需通过 super 手动调用父类构造函数。
示例:
class Animals {
void eat() => print("Eating food");
}
class Panda extends Animals {
@override
void eat() => print("Panda eating food"); // 重写父类方法
}
2. implements(接口实现)
定义:强制类 完全实现接口的所有成员(包括方法和属性),不继承任何具体实现。
特点:
一个类可同时实现多个接口(多继承);
必须覆盖接口中所有的抽象成员和已实现成员;
适用于定义严格的行为契约(如抽象类的具体化)。
abstract class Flyable {
void fly();
}
class Bird implements Flyable {
@override
void fly() => print("Bird flying"); // 必须实现接口方法
}
3. mixin(混入)
定义:通过 with 关键字将多个类的功能 组合到当前类,主要用于 横向复用代码,规避单继承限制。
特点:
混入类需通过 mixin 关键字声明,不能有构造函数;
支持 线性化继承(后混入的类覆盖前者的同名方法);
可使用 on 限制混入类的适用范围。
示例:
mixin Swimmer {
void swim() => print("Swimming...");
}
class Dolphin with Swimmer {} // 直接复用 Swimmer 的方法
三者的核心区别:
特性 | extends | implements | mixin |
---|---|---|---|
继承关系 | 单继承 | 可实现多接口 | 可混入多类 |
代码复用方式 | 继承具体实现 | 重新实现所有成员 | 组合已有实现 |
方法覆盖 | 可选重写 | 必须完全实现 | 按混入顺序覆盖 |
主要用途 | 建立父子类关系 | 定义行为契约 | 横向功能复用 |
使用顺序规则:
Dart 中若同时使用三者,优先级为:extends → with(混入)→ implements。例如:
class Example extends Parent with MixinA, MixinB implements InterfaceA, InterfaceB { .
.. }
五、Flutter和原生通讯有几种通道?有什么区别?
Flutter应用与原生平台之间进行通信。主要有三种类型的通道:
-
MethodChannel:支持双向通信,既可以Flutter调用原生方法并获取返回值,也可以原生调用Flutter方法并获取返回值。适用于需要主动触发原生能力的场景,如调用原生相机、分享功能、获取设备信息等
-
EventChannel:主要用于原生向Flutter发送数据流,适用于需要实时传递数据的场景,如传感器数据、位置更新等。它支持单向通信,没有返回值。
-
BasicMessageChannel:BasicMessageChannel用于传递字符串、二进制数据等基本类型的数据,适用于简单的数据交换场景。它支持双向传递,但主要用于传递基本类型的数据。