你可能熟悉 Flutter,但了解 Flutter 基础知识是更好开发的主要步骤之一。您应该知道应用程序生命周期是如何创建、呈现、更新和处置的。这些知识可以帮助您开发高效且强大的应用程序。
如果为 Android 或 iOS 开发过应用程序,那么一定听说过应用程序生命周期状态。比如活跃、不活跃、挂起等。今天我们将讨论 Flutter 中的应用生命周期。在 Flutter 中,我们主要讨论了 Stateful Widget 的 Lifecycle 和 App 的 Lifecycle 两部分的生命周期。
Flutter 中的应用生命周期
App Lifecycle 通知我们应用程序的当前状态。 Flutter 应用程序有 4 种可能的状态。 AppLifeCycle 枚举为我们提供了以下选项:
- detached:应用程序仍然托管在 FlutterEngine 上(FlutterEngine 是可以在 Android 应用程序中运行 Dart 代码的容器)。在这里,引擎在没有视图的情况下运行,它要么正在构建视图,要么没有要显示的视图。
- inactive:应用程序处于非活动状态,未接收用户输入。在 iOS 上,这可能意味着应用程序由于电话呼叫、触摸 ID 等而处于转换状态。在 Android 上,这意味着应用程序处于分屏、电话呼叫、系统对话框等状态。
- paused:应用程序当前对用户不可见并且在后台运行,它没有接收任何用户输入。
- resumed:应用程序对用户可见并且正在接收用户输入。
现在,我们已经了解了 App Lifecycle 状态的基本知识,让我们来看看如何监听这些事件。
监听应用生命周期事件
默认情况下,我们无法监听!我们需要使用 WidgetsBindingObserver 类的 App Lifecycle 事件。我们可以像这样在有状态的 widget 中做到这一点:
class MyApp extends StatefulWidget {
MyApp({Key? key}) : super(key: key);
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
...
}
我们可以使用无状态 widget 来做同样的事情:
class MyApp extends StatelessWidget with WidgetsBindingObserver{...}
此时我们也不会收到任何 App Lifecycle 事件,我们需要将当前类 (this) 作为观察者添加到 WidgetsBinding 实例。请注意,我们也必须手动删除观察者。 Stateful widget 的代码如下所示:
@override
void initState() {
super.initState();
WidgetsBinding.instance!.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance!.removeObserver(this);
super.dispose();
}
在有状态的 widget 中,initState 和 dispose 是添加和删除观察者的理想场所。在这里, addObserver 将当前上下文添加到观察者列表中,而 removeObserver 从观察者列表中删除当前上下文。
为了在无状态 widget 中做同样的事情,我们必须找到一种解决方法。我们可以在构造函数中添加观察者,并在按下后退按钮时移除观察者。在无状态 widget 中添加和删除观察者的代码将是:
import 'package:flutter/material.dart';
class HomePage extends StatelessWidget with WidgetsBindingObserver {
HomePage({Key? key}) : super(key: key) {
WidgetsBinding.instance!.addObserver(this);
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
WidgetsBinding.instance!.removeObserver(this);
return true;
},
child: Scaffold(),
);
}
}
现在有状态和无状态 widget 都能够监听生命周期事件。我们现在可以简单地覆盖 didChangeAppLifecycleState 方法。
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
print("Resumed");
}
if (state == AppLifecycleState.detached) {
print("Detached");
}
if (state == AppLifecycleState.inactive) {
print("Inactive");
}
if (state == AppLifecycleState.paused) {
print("Paused");
}
}
我们可以轻松地监听应用程序事件并获得应用程序级别的更新。现在,您可以在应用程序移入后台、分离或返回前台时收到通知。现在让我们看看有状态 widget 的生命周期。
Flutter 中 Stateful Widget 的生命周期
在 Flutter 应用程序中,每个元素都是一个 widget ,因此状态生命周期取决于使用的 widget 类型。在 Flutter 中主要有两种类型的 widget :
- 无状态 widget
- 有状态的 widget
无状态 widget
无状态 widget 是那些在运行时不改变状态的 widget ,它具有不可变的状态。这些 widget 是永久性的,一旦构建就不会改变它们的状态。这些是不需要在任何时间点更改其状态的 widget 。例如:按钮、列表项等。
import 'package:flutter/material.dart';
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container();
}
}
有状态的 widget
有状态的 widget 是那些可以在运行时更改其状态的 widget ,即它具有可变状态。这些 widget 是非永久性的,因此它们的状态会在其属性被修改时发生变化。在这里,要更新状态,请使用 setState((){}) 函数。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Container();
}
}
在 Stateful Widget 中,我们提供了生命周期方法。所以我们现在将关注有状态的 widget ,因为它们处理状态。我们来看看提供的方法。
createState()
当我们创建 Stateful Widget 时会调用此方法。 createState() 在树中的给定位置为这个 widget 创建可变状态。
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
其余所有有状态的 widget 生命周期方法都在类的状态部分中被覆盖,即:
class _MyHomePageState extends State<MyHomePage>{}
initState()
一旦调用 createState() 函数,就会调用它。 initState() 只执行一次。此代码在 widget 呈现之前运行,因此此时上下文无效。
这个方法需要调用super.initState()。这里执行变量、流、动画控制器、滚动控制器等的初始化。
@override
void initState(){
// Initialize your objects here
super.initState();
}
didChangeDependencies()
此方法在 initState() 之后直接调用。 didChangeDependencies() 主要在该 State 类的依赖项发生变化时调用。这很少被覆盖,因为其他包提供了优化的此类功能。
示例:如果之前对 build 的调用引用了后来更改的 InheritedWidget,则框架将调用此方法以通知此对象有关更改。
@override
void didChangeDependencies() {
super.didChangeDependencies();
}
build()
这个函数定义了这个 Stateful Widget 的用户界面。必须实现此功能。框架可以在以下任何一种情况下调用此函数:
- initState 之后。
- didUpdateWidget 之后。
- 当我们调用 setState 来更新状态时。
- 当此 State 对象的依赖项发生更改时。
- 框架用此方法返回的 Widget 替换此 Widget 下方的子树。
@override
Widget build(BuildContext context) {
return Scaffold();
}
didUpdateWidget()
当父 Widget 配置更改时使用。如果父级的属性发生变化,那么我们需要更新当前的子 Widget ,也就是调用此函数的时间。它主要发生在我们在调试时热重载应用程序的情况下。
@override
void didUpdateWidget(covariant Trying oldWidget) {
super.didUpdateWidget(oldWidget);
}
deactivate() and activate()
当 Widget 暂时从树中移除时调用 deactivate(),它可能会在未来加入 Widget 树。使用 activate() 方法将停用的 Widget 移回 Widget 树中。这些功能不经常使用。
@override
void deactivate() {
// TODO: implement deactivate
super.deactivate();
}
@override
void activate() {
// TODO: implement activate
super.activate();
}
dispose()
一个经常使用的函数,被调用来释放当前 widget 持有的所有资源。在这里,取消订阅手动侦听的所有事件,如流、控制器、计时器等。通常处理 initState() 中初始化的值。
结论
在这篇文章中,详细解释了 Flutter 中的两种生命周期。我们查看了 App Lifecycle 和 Stateful Widget 生命周期。