Flutter 頁面的生命周期
1. 創(chuàng)建初始化階段 (Creation)
-
constructor: Widget 的構(gòu)造函數(shù)首先被調(diào)用 -
createState(): 對于 StatefulWidget,這個(gè)方法被調(diào)用并返回關(guān)聯(lián)的 State 對象 -
initState(): State 對象被插入到 widget 樹中時(shí)調(diào)用(只調(diào)用一次)
@override //初始化工作,如訂閱流、初始化變量等
void initState() {
super.initState();
}
2. 構(gòu)建階段 (Building)
-
didChangeDependencies(): 在initState()之后立即調(diào)用,當(dāng) State 對象的依賴項(xiàng)發(fā)生變化時(shí)也會(huì)調(diào)用 -
build(): 構(gòu)建 widget 樹的主要方法,會(huì)被多次調(diào)用
@override
Widget build(BuildContext context) {
return Scaffold(// 構(gòu)建UI
);
}
3. 更新階段 (Updating)
-
didUpdateWidget(): 當(dāng) widget 配置更改時(shí)調(diào)用(父 widget 重建并傳入新 widget) -
setState(): 通知框架狀態(tài)已更改,需要重新構(gòu)建
4. 銷毀階段 (Destruction)
-
deactivate(): 當(dāng) State 對象從樹中移除時(shí)調(diào)用 -
dispose(): 當(dāng) State 對象被永久移除時(shí)調(diào)用(釋放資源)
@override //清理工作,如取消訂閱、關(guān)閉控制器等
void dispose() {
super.dispose();
}
完整的生命周期流程
-
createState()→ 2.initState()→ 3.didChangeDependencies()→ 4.build()→
(更新循環(huán):didUpdateWidget()→build()) → -
deactivate()→ 6.dispose()
頁面導(dǎo)航相關(guān)生命周期
當(dāng)使用 Navigator 進(jìn)行頁面導(dǎo)航時(shí),還會(huì)涉及以下方法:
-
Navigator.push(): 新頁面進(jìn)入時(shí),原頁面的deactivate()被調(diào)用但不dispose() -
Navigator.pop(): 返回時(shí)原頁面的build()會(huì)再次被調(diào)用 -
RouteAware: 可以實(shí)現(xiàn)更精細(xì)的路由感知生命周期
1. 什么是Flutter?
答案:Flutter是Google開發(fā)的開源UI工具包,用于從單一代碼庫構(gòu)建跨平臺(tái)的移動(dòng)、web和桌面應(yīng)用。它使用Dart語言,并提供豐富的預(yù)構(gòu)建組件(widgets)和強(qiáng)大的渲染引擎。
2. Flutter的主要特點(diǎn)是什么?
- 跨平臺(tái)開發(fā)(iOS、Android、Web、桌面)
- 高性能(直接編譯為原生代碼)
- 熱重載(Hot Reload)功能
- 豐富的widget庫
- 自定義UI設(shè)計(jì)能力
- 單一代碼庫
3. 什么是Widget?Flutter中有哪些主要類型的Widget?
答案:Widget是Flutter應(yīng)用的基本構(gòu)建塊,描述了UI元素的配置。主要類型有:
有狀態(tài)Widget(StatefulWidget):可變的,有內(nèi)部狀態(tài)
無狀態(tài)Widget(StatelessWidget):不可變的,無內(nèi)部狀態(tài)
繼承Widget(InheritedWidget):數(shù)據(jù)共享
4. 解釋StatefulWidget和StatelessWidget的區(qū)別
StatelessWidget:一旦創(chuàng)建就不能改變,沒有內(nèi)部狀態(tài),build方法只依賴于傳入的參數(shù)
StatefulWidget:可以動(dòng)態(tài)改變,有內(nèi)部狀態(tài)(通過State類管理),當(dāng)狀態(tài)改變時(shí)會(huì)重新構(gòu)建
5. 什么是Flutter的熱重載(Hot Reload)?
答案:熱重載是Flutter的開發(fā)功能,允許在不重啟應(yīng)用的情況下快速查看代碼更改的效果。它保持應(yīng)用狀態(tài),只更新修改的部分,大大提高了開發(fā)效率。
中級部分
6. 解釋Flutter的渲染流程
- 構(gòu)建Widget樹
- 創(chuàng)建Element樹(Widget的實(shí)例化)
- 生成RenderObject樹(布局和繪制)
- 布局(確定大小和位置)
- 繪制(生成視覺元素)
7. 什么是BuildContext?
答案:BuildContext是Widget在Widget樹中位置的句柄,用于:
-查找父級Widget
-訪問主題(Theme)等共享數(shù)據(jù)
-導(dǎo)航(Navigator)操作
每個(gè)Widget的build方法都會(huì)接收一個(gè)BuildContext參數(shù)。
8. 如何在Flutter中處理用戶交互?
- 使用GestureDetector檢測手勢(點(diǎn)擊、滑動(dòng)等)
- 使用InkWell提供Material Design風(fēng)格的水波紋效果
- 直接監(jiān)聽RawGestureDetector處理原始手勢
- 使用Listener處理原始指針事件
9. 解釋Flutter中的Key及其用途
答案:Key是Widget、Element和SemanticsNode的唯一標(biāo)識符,主要用于:
- 保留狀態(tài)當(dāng)Widget在樹中移動(dòng)時(shí)
- 在集合中唯一標(biāo)識Widget(如列表項(xiàng))
- 強(qiáng)制重建特定Widget
常見類型:GlobalKey(全局唯一)、LocalKey、UniqueKey、ObjectKey等。
10. 如何在Flutter中實(shí)現(xiàn)導(dǎo)航?
// 導(dǎo)航到新頁面
Navigator.push(context, MaterialPageRoute(builder: (context) => NewPage()));
// 返回上一頁
Navigator.pop(context);
// 命名路由
Navigator.pushNamed(context, '/details');
需要在MaterialApp中配置路由表。
高級部分
11. 解釋Flutter的狀態(tài)管理方案
- setState:簡單狀態(tài)管理
- InheritedWidget:共享數(shù)據(jù)
- Provider:推薦的基礎(chǔ)狀態(tài)管理
- GetX:輕量級全功能方案
- Bloc/RxDart:響應(yīng)式編程
- Redux:單向數(shù)據(jù)流
- Riverpod:Provider的改進(jìn)版
12. 什么是Flutter的Platform Channels?
答案:Platform Channels允許Flutter與平臺(tái)特定代碼(Android/iOS)通信:
- MethodChannel:異步方法調(diào)用
- EventChannel:事件流通信
- BasicMessageChannel:基本消息傳遞
用于訪問平臺(tái)原生功能(如傳感器、藍(lán)牙等)。
13. 如何優(yōu)化Flutter應(yīng)用的性能?
- 使用const構(gòu)造函數(shù)
- 避免不必要的重建(使用shouldRepaint)
- 對長列表使用ListView.builder
- 減少Widget樹的深度
- 使用RepaintBoundary隔離重繪區(qū)域
- 避免在build方法中進(jìn)行耗時(shí)操作
- 使用性能分析工具(Flutter DevTools)
14. 解釋Flutter中的動(dòng)畫系統(tǒng)
Flutter動(dòng)畫基于AnimationController和Tween:
- AnimationController:控制動(dòng)畫的播放、停止、反轉(zhuǎn)
- Tween:定義動(dòng)畫的起始和結(jié)束值
- Animation:生成介于兩者之間的值
- 使用AnimatedBuilder或AnimatedWidget高效重建
15. 什么是Isolate?如何在Flutter中使用?
答案:Isolate是Dart的并發(fā)模型,類似于線程但有獨(dú)立內(nèi)存空間。用于執(zhí)行CPU密集型任務(wù):
void longRunningTask() {
// 耗時(shí)操作
}
void main() async {
await Isolate.spawn(longRunningTask, null);
}
使用compute函數(shù)簡化Isolate通信。
架構(gòu)和設(shè)計(jì)模式
16. 解釋BLoC模式
答案:BLoC(Business Logic Component)模式:
- 分離業(yè)務(wù)邏輯和UI
- 使用Streams處理數(shù)據(jù)流
- 輸入和輸出(Sink/Stream)
- 通常與Provider一起使用
- 適合復(fù)雜狀態(tài)管理場景
17. 什么是Flutter的Provider模式?
答案:Provider是基于InheritedWidget的包裝器,簡化狀態(tài)管理:
- 提供數(shù)據(jù)共享
- 當(dāng)數(shù)據(jù)變化時(shí)自動(dòng)重建依賴的Widget
- 多種Provider類型(ChangeNotifierProvider、FutureProvider等)
- 比直接使用setState更高效
18. 如何在Flutter中實(shí)現(xiàn)MVVM?
- Model:數(shù)據(jù)層
- View:UI層(Widget)
- ViewModel:業(yè)務(wù)邏輯,使用ChangeNotifier或Stream
- 使用Provider或GetIt連接View和ViewModel
- View監(jiān)聽ViewModel的狀態(tài)變化
19. 解釋Flutter的響應(yīng)式編程
答案:
- 基于Stream和RxDart
- 數(shù)據(jù)作為事件流處理
- 使用StreamBuilder構(gòu)建UI
- 操作符(map、where、debounce等)轉(zhuǎn)換流
- 適合實(shí)時(shí)數(shù)據(jù)應(yīng)用
20. 什么是Flutter的Element和RenderObject?
答案:
- Element:Widget的實(shí)例,管理生命周期和更新
- RenderObject:處理布局和繪制
- Widget:不可變的配置描述
- 三者關(guān)系:Widget創(chuàng)建Element,Element創(chuàng)建/更新RenderObject
實(shí)踐問題
21. 如何在Flutter中處理網(wǎng)絡(luò)請求?
答案:
使用http或dio包:
import 'package:http/http.dart' as http;
Future<void> fetchData() async {
final response = await http.get(Uri.parse('https://api.example.com/data'));
if (response.statusCode == 200) {
// 處理數(shù)據(jù)
}
}
使用FutureBuilder顯示異步數(shù)據(jù)。
22. Flutter中如何實(shí)現(xiàn)本地存儲(chǔ)?
- SharedPreferences:簡單鍵值對存儲(chǔ)
- SQLite:使用sqflite包
- Hive:輕量級NoSQL數(shù)據(jù)庫
- 文件存儲(chǔ):使用path_provider和dart:io
23. 如何在Flutter中實(shí)現(xiàn)主題切換?
MaterialApp(
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
themeMode: ThemeMode.system, // 或.dark/.light
);
使用Provider管理自定義主題狀態(tài)。
24. Flutter中如何處理多語言國際化?
使用flutter_localizations和intl包:
- 創(chuàng)建arb文件存儲(chǔ)翻譯
- 配置MaterialApp的localizationsDelegates和supportedLocales
- 使用AppLocalizations.of(context)獲取翻譯
25. 如何測試Flutter應(yīng)用?
- 單元測試:測試獨(dú)立函數(shù)/類
- Widget測試:測試單個(gè)Widget
- 集成測試:測試完整應(yīng)用流程
- 使用test和flutter_test包
- 使用Mockito進(jìn)行模擬測試
進(jìn)階問題
26. 什么是Flutter的CustomPaint?
答案:CustomPaint是一個(gè)Widget,允許自定義繪制:
- 使用CustomPainter子類
- 重寫paint方法使用Canvas繪制
- 可以繪制任意2D圖形
- 適合高度自定義的UI元素
27. 解釋Flutter的Hero動(dòng)畫
答案:Hero動(dòng)畫用于在不同頁面間共享元素的平滑過渡:
- 在兩個(gè)頁面使用相同tag的Hero Widget
- 框架自動(dòng)處理過渡動(dòng)畫
- 可以自定義過渡行為
- 常用于圖片/卡片在列表和詳情頁間的過渡
28. 什么是Flutter的Sliver?
答案:Sliver是用于CustomScrollView的可滾動(dòng)區(qū)域的特化Widget:
- SliverAppBar:可折疊的AppBar
- SliverList/SliverGrid:列表和網(wǎng)格
- SliverToBoxAdapter:包裝普通Widget
- SliverPersistentHeader:固定頭部
- 實(shí)現(xiàn)復(fù)雜的滾動(dòng)效果
29. 如何在Flutter中實(shí)現(xiàn)深度鏈接?
- 配置Android的intent-filter和iOS的URL Scheme
- 使用uni_links或go_router包處理鏈接
- 解析鏈接路由到相應(yīng)頁面
- 處理冷啟動(dòng)和熱啟動(dòng)場景
30. Flutter Web和原生Flutter有什么區(qū)別?
- 渲染:Web使用HTML/CSS/Canvas,原生使用Skia
- 插件支持:部分插件不支持Web
- 性能:動(dòng)畫和復(fù)雜UI在Web上可能稍慢
- 打包:輸出為Web資源而非原生二進(jìn)制
- 路由:基于瀏覽器的導(dǎo)航
- 文件系統(tǒng)訪問受限