1. main() 函數(shù):
這是應(yīng)用程序的入口點(diǎn),其中初始化了Flutter框架,并調(diào)用 runApp() 函數(shù)來(lái)啟動(dòng)應(yīng)用程序。
2. runApp():
在 main() 函數(shù)中調(diào)用 runApp() 函數(shù)來(lái)啟動(dòng)應(yīng)用程序。它會(huì)創(chuàng)建一個(gè)實(shí)例,并將其渲染到設(shè)備的屏幕上。(WidgetsApp 或 MaterialApp)
3. 應(yīng)用程序啟動(dòng):
當(dāng)應(yīng)用程序啟動(dòng)時(shí),會(huì)觸發(fā) WidgetsApp 或 MaterialApp 的生命周期回調(diào)方法。
didChangeAppLifecycleState:當(dāng)應(yīng)用程序的生命周期狀態(tài)發(fā)生變化時(shí)調(diào)用,例如應(yīng)用程序進(jìn)入前臺(tái)或后臺(tái)。
didChangeAccessibilityFeatures:當(dāng)設(shè)備的輔助功能設(shè)置發(fā)生變化時(shí)調(diào)用。
didChangeLocales:當(dāng)設(shè)備的區(qū)域設(shè)置發(fā)生變化時(shí)調(diào)用。
onGenerateRoute:根據(jù)指定的路由生成頁(yè)面的回調(diào)方法。
4. build() 方法:
在啟動(dòng)應(yīng)用程序后,會(huì)調(diào)用 build() 方法來(lái)構(gòu)建應(yīng)用程序的用戶界面。該方法通常返回一個(gè) Widget,表示應(yīng)用程序的根界面。
StatelessWidget的生命周期:
StatelessWidget是一種無(wú)狀態(tài)的Widget,在Flutter中沒(méi)有顯式的生命周期方法。StatelessWidget的生命周期相對(duì)簡(jiǎn)單,只有一次構(gòu)建過(guò)程。
當(dāng)使用StatelessWidget構(gòu)建一個(gè)Widget時(shí),F(xiàn)lutter會(huì)調(diào)用該Widget的build()方法來(lái)構(gòu)建UI。在這個(gè)過(guò)程中,F(xiàn)lutter會(huì)根據(jù)Widget的屬性和父級(jí)Widget的狀態(tài)來(lái)創(chuàng)建并返回Widget樹(shù)。一旦構(gòu)建完成,StatelessWidget的工作就完成了,它不會(huì)存儲(chǔ)狀態(tài)也不會(huì)發(fā)生變化。
每當(dāng)需要更新StatelessWidget的UI時(shí),F(xiàn)lutter會(huì)創(chuàng)建一個(gè)新的StatelessWidget實(shí)例,并重新調(diào)用其build()方法進(jìn)行UI的重建。這意味著StatelessWidget是完全無(wú)狀態(tài)的,它不會(huì)保留任何狀態(tài)信息,也不會(huì)處理用戶交互或觸發(fā)更新。
簡(jiǎn)單來(lái)說(shuō),StatelessWidget的生命周期只包括一次構(gòu)建過(guò)程,它只負(fù)責(zé)根據(jù)輸入屬性構(gòu)建UI,不會(huì)存儲(chǔ)狀態(tài)或處理更新。因此,StatelessWidget適用于展示靜態(tài)內(nèi)容或只依賴于傳入?yún)?shù)的情況,它們更加簡(jiǎn)單和輕量,也更高效地構(gòu)建和渲染。
StatefulWidget生命周期:
Flutter框架會(huì)根據(jù)需要?jiǎng)?chuàng)建、更新和銷毀小部件,并調(diào)用相應(yīng)的生命周期方法。
(1) createState:
用于創(chuàng)建一個(gè)widget狀態(tài)對(duì)象(state object)。小部件(Widget)和狀態(tài)對(duì)象(State)是分離的,小部件負(fù)責(zé)構(gòu)建用戶界面,而狀態(tài)對(duì)象負(fù)責(zé)存儲(chǔ)和管理與小部件相關(guān)的狀態(tài)信息。
(2) initState:
用于初始化一個(gè)狀態(tài)對(duì)象(State object)。當(dāng)widget的狀態(tài)對(duì)象被創(chuàng)建時(shí),都會(huì)調(diào)用該方法。
當(dāng)widget被插入到widget樹(shù)中時(shí),F(xiàn)lutter框架會(huì)創(chuàng)建一個(gè)對(duì)應(yīng)的狀態(tài)對(duì)象,并調(diào)用該狀態(tài)對(duì)象的 initState 方法。這個(gè)方法通常被重寫(xiě),用于執(zhí)行一些初始化操作,例如設(shè)置初始值、訂閱事件或執(zhí)行一次性的配置。
initState 方法只會(huì)被調(diào)用一次,即在widget被插入到widget樹(shù)中時(shí)。
(3) didChangeDependencies:
用于處理widget依賴關(guān)系的變化。當(dāng)widget依賴的信息發(fā)生變化時(shí),會(huì)調(diào)用該方法。
當(dāng)一個(gè)widget首次構(gòu)建時(shí),或者其依賴的信息發(fā)生變化時(shí)(例如父級(jí)widget的狀態(tài)發(fā)生變化),會(huì)調(diào)用widget的 didChangeDependencies 方法。這個(gè)方法通常被重寫(xiě),用于執(zhí)行與依賴關(guān)系變化相關(guān)的操作,例如更新數(shù)據(jù)、重新訂閱流、調(diào)用接口等。
(4) build:
當(dāng)widget的狀態(tài)發(fā)生變化、依賴關(guān)系發(fā)生變化或者父級(jí)widget請(qǐng)求重建時(shí),F(xiàn)lutter框架會(huì)調(diào)用widget的 build 方法。這個(gè)方法是必須被重寫(xiě)的,用于返回一個(gè) Widget 對(duì)象。會(huì)多次調(diào)用。
(5) didUpdateWidget:
當(dāng)一個(gè)widget的配置發(fā)生變化時(shí),會(huì)調(diào)用該方法。
當(dāng)widget被更新時(shí),會(huì)調(diào)用widget的此方法。這個(gè)方法通常被重寫(xiě),用于執(zhí)行與更新相關(guān)的操作,例如更新?tīng)顟B(tài)、重新訂閱流、刷新數(shù)據(jù)等。
didUpdateWidget 方法在首次構(gòu)建widget時(shí)不會(huì)被調(diào)用,它只在widget配置發(fā)生變化時(shí)被調(diào)用。
widget的配置發(fā)生變化,指的是widget所接收的參數(shù)或?qū)傩园l(fā)生了變化。這包括widget的構(gòu)造函數(shù)參數(shù)、父級(jí)widget傳遞的數(shù)據(jù)、或者通過(guò)依賴關(guān)系更新的數(shù)據(jù)等。
當(dāng)父級(jí)widget重新構(gòu)建時(shí),如果傳遞給子級(jí)widget的參數(shù)發(fā)生了變化,或者父級(jí)widget通過(guò)setState方法更新了狀態(tài),那么子級(jí)widget的配置就會(huì)發(fā)生變化。這時(shí),F(xiàn)lutter框架會(huì)銷毀舊的子級(jí)widget實(shí)例,并創(chuàng)建一個(gè)新的子級(jí)widget實(shí)例來(lái)替代它,同時(shí)調(diào)用新實(shí)例的build方法。
(6) deactivate:
當(dāng)widget件樹(shù)中被移除時(shí)調(diào)用。它標(biāo)志著widget即將被銷毀,但可以在這個(gè)方法中執(zhí)行一些清理工作。
當(dāng)一個(gè)widget被從widget樹(shù)中移除時(shí),會(huì)調(diào)用widget的 deactivate 方法。這個(gè)方法通常被重寫(xiě),用于釋放資源、取消訂閱、停止動(dòng)畫(huà)等清理操作。
要注意的是,deactivate 方法不一定會(huì)被立即調(diào)用。具體的調(diào)用時(shí)機(jī)可能取決于widget樹(shù)的重建、路由的切換等因素。因此,不要在 deactivate 方法中假設(shè)widget立即被銷毀。
通過(guò)使用 deactivate 方法,您可以在小部件被移除時(shí)執(zhí)行一些清理工作,以釋放資源、取消訂閱、停止動(dòng)畫(huà)等。這樣可以確保小部件在被銷毀之前進(jìn)行必要的清理操作,并提供更好的性能和資源管理。
(7) dispose:
當(dāng)widget被永久移除并銷毀時(shí)調(diào)用。它標(biāo)志著widget的生命周期結(jié)束,可以在這個(gè)方法中執(zhí)行最終的清理工作。
當(dāng)一個(gè)widget被永久移除并銷毀時(shí),F(xiàn)lutter框架會(huì)調(diào)用widget的 dispose 方法。這個(gè)方法通常被重寫(xiě),用于釋放資源、取消訂閱、停止動(dòng)畫(huà)等最終的清理操作。
dispose 和 deactivate 是小部件在生命周期結(jié)束時(shí)的兩個(gè)不同階段。
deactivate 方法在widget從widget樹(shù)中被移除時(shí)調(diào)用,標(biāo)志著widget即將被銷毀。在 deactivate 方法中,可以執(zhí)行一些清理工作,例如釋放資源、取消訂閱、停止動(dòng)畫(huà)等。deactivate 方法通常在widget不再可見(jiàn)或不再被需要時(shí)調(diào)用,但具體的調(diào)用時(shí)機(jī)可能取決于widget樹(shù)的重建、路由的切換等因素。
dispose 方法在widget被永久移除并銷毀時(shí)調(diào)用,標(biāo)志著widget的生命周期結(jié)束。在 dispose 方法中,可以執(zhí)行最終的清理工作,例如釋放資源、取消訂閱、停止動(dòng)畫(huà)等。dispose 方法通常在小部件被銷毀時(shí)調(diào)用,但具體的調(diào)用時(shí)機(jī)可能取決于小部件樹(shù)的重建、路由的切換等因素。
需要注意的是,deactivate 方法可能會(huì)在 dispose 方法之前被調(diào)用。這是因?yàn)樵趙idget從widget樹(shù)中被移除時(shí),它首先會(huì)被標(biāo)記為不再活動(dòng)(deactivate),然后才會(huì)被永久移除和銷毀(dispose)。
5. 應(yīng)用程序關(guān)閉:
當(dāng)應(yīng)用程序關(guān)閉時(shí),會(huì)觸發(fā)相應(yīng)的生命周期回調(diào)方法。
-
dispose:在應(yīng)用程序關(guān)閉前,最后一個(gè)小部件被永久刪除時(shí)調(diào)用,用于釋放資源和取消訂閱。
生命周期狀態(tài)
mounted:表示 State 對(duì)象已插入到樹(shù)中。
用于表示widget當(dāng)前是否已經(jīng)插入到小部件樹(shù)中。
當(dāng)一個(gè)widget被插入到widget樹(shù)中時(shí),它的 mounted 屬性會(huì)被設(shè)置為 true。當(dāng)widget被永久移除并銷毀時(shí),它的 mounted 屬性會(huì)被設(shè)置為 false。
mounted 屬性通常用于檢查widget是否仍然存在于widget樹(shù)中。在某些情況下,當(dāng)異步操作或回調(diào)函數(shù)觸發(fā)時(shí),widget可能已經(jīng)被移除,但回調(diào)函數(shù)仍然被調(diào)用。在這種情況下,通過(guò)檢查 mounted 屬性可以避免對(duì)已經(jīng)被移除的widget進(jìn)行無(wú)效操作。
unmounted:表示 State 對(duì)象已被永久從樹(shù)中移除。
應(yīng)用程序生命周期
onResume:當(dāng)應(yīng)用程序從后臺(tái)進(jìn)入前臺(tái)時(shí)調(diào)用。
onPause:當(dāng)應(yīng)用程序從前臺(tái)進(jìn)入后臺(tái)時(shí)調(diào)用。
onLaunch:當(dāng)應(yīng)用程序被啟動(dòng)時(shí)調(diào)用。
onTerminate:當(dāng)應(yīng)用程序被終止時(shí)調(diào)用。注意,此方法不會(huì)在 iOS 上被調(diào)用,因?yàn)?iOS 不允許應(yīng)用程序自我終止。
以上就是 Flutter 應(yīng)用程序的生命周期。理解這些生命周期可以幫助開(kāi)發(fā)人員編寫(xiě)更好的 Flutter 應(yīng)用程序,并在應(yīng)用程序的不同階段執(zhí)行必要的操作。
flutter 如何監(jiān)聽(tīng)命周期狀態(tài)發(fā)生:
在Flutter中,可以通過(guò)WidgetsBindingObserver接口來(lái)監(jiān)聽(tīng)?wèi)?yīng)用程序的生命周期狀態(tài)的變化。WidgetsBindingObserver是一個(gè)觀察者接口,它定義了一組回調(diào)方法,可以在應(yīng)用程序的生命周期狀態(tài)發(fā)生變化時(shí)進(jìn)行相應(yīng)的處理。
//1 在需要監(jiān)聽(tīng)生命周期的Widget中實(shí)現(xiàn)WidgetsBindingObserver接口。例如,你可以在State對(duì)象中實(shí)現(xiàn)它:
class MyWidgetState extends State with WidgetsBindingObserver {
// ...
}
//2 在State對(duì)象中重寫(xiě)didChangeAppLifecycleState方法。該方法會(huì)在應(yīng)用程序的生命周期狀態(tài)發(fā)生變化時(shí)被調(diào)用,它接收一個(gè)AppLifecycleState枚舉類型的參數(shù),表示當(dāng)前的生命周期狀態(tài)。
class MyWidgetState extends State with WidgetsBindingObserver {
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
// 在這里處理生命周期狀態(tài)的變化
if (state == AppLifecycleState.resumed) {
// 應(yīng)用程序從后臺(tái)恢復(fù)到前臺(tái)
} else if (state == AppLifecycleState.paused) {
// 應(yīng)用程序從前臺(tái)進(jìn)入后臺(tái)
}
}
}
//3 在State對(duì)象的初始化方法(如initState())中注WidgetsBindingObserver
class MyWidgetState extends State with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
// ...
}
//4 在State對(duì)象的銷毀方法(如dispose())中注銷WidgetsBindingObserver。
dart
class MyWidgetState extends State with WidgetsBindingObserver {
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
// ...
}
onGenerateRoute 路由管理
onGenerateRoute是一個(gè)可選的回調(diào)函數(shù),它可以在Flutter應(yīng)用程序中用來(lái)動(dòng)態(tài)生成路由(routes)的回調(diào)函數(shù)。當(dāng)導(dǎo)航器(Navigator)無(wú)法找到與指定路由名稱相匹配的路由時(shí),會(huì)調(diào)用onGenerateRoute來(lái)生成相應(yīng)的路由。通常,onGenerateRoute函數(shù)用于實(shí)現(xiàn)動(dòng)態(tài)路由,即根據(jù)路由名稱和參數(shù)生成相應(yīng)的路由。它常用于處理未知路由、動(dòng)態(tài)路由、路由傳參等情況。
MaterialApp(
// ... 其他配置
onGenerateRoute: (settings) {
if (settings.name == '/profile') {
// 生成名為'/profile'的路由
return MaterialPageRoute(
builder: (context) => ProfileScreen(),
);
} else if (settings.name == '/settings') {
// 生成名為'/settings'的路由
return MaterialPageRoute(
builder: (context) => SettingsScreen(),
);
}
// 其他未知路由,可以返回一個(gè)默認(rèn)的路由或錯(cuò)誤頁(yè)面
return MaterialPageRoute(
builder: (context) => UnknownRouteScreen(),
);
},
);
// 使用
Navigator.pushNamed(context, '/profile');