OverlayEntries 和路由的重建優化
摘要
#此優化改善了路由轉場的效能,但可能會發現應用程式中遺漏的 setState
呼叫。
背景
#在進行此變更之前,當在其上方新增或移除新的不透明項目時,OverlayEntry
會重建。這些重建是不必要的,因為它們不是由受影響的 OverlayEntry
的狀態變更所觸發。此重大變更優化了我們處理 OverlayEntry
新增和移除的方式,並移除了不必要的重建以改善效能。
由於 Navigator
內部將每個 Route
放入一個 OverlayEntry
中,此變更也適用於 Route
的轉場效果:如果一個不透明的 Route
被推到另一個 Route
的上方,或從上方移除,則不透明 Route
下方的 Route
不會再不必要地重建。
變更說明
#在大多數情況下,此變更不需要您修改任何程式碼。但是,如果您的應用程式錯誤地依賴於隱式的重建,您可能會遇到問題,這些問題可以透過將任何狀態變更包裝在 setState
呼叫中來解決。
此外,此變更稍微修改了 widget 樹的形狀:在此變更之前,OverlayEntry
被包裹在一個 Stack
widget 中。顯式的 Stack
widget 已從 widget 階層中移除。
移轉指南
#如果您在升級到包含此變更的 Flutter 版本後遇到問題,請檢查您的程式碼中是否有遺漏對 setState
的呼叫。在下面的範例中,將 Navigator.pushNamed
的返回值賦值給 buttonLabel
是隱式地修改狀態,應該將其包裝在一個顯式的 setState
呼叫中。
遷移前的程式碼
class FooState extends State<Foo> {
String buttonLabel = 'Click Me';
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () async {
// Illegal state modification that should be wrapped in setState.
buttonLabel = await Navigator.pushNamed(context, '/bar');
},
child: Text(buttonLabel),
);
}
}
遷移後的程式碼
class FooState extends State<Foo> {
String buttonLabel = 'Click Me';
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () async {
final newLabel = await Navigator.pushNamed(context, '/bar');
setState(() {
buttonLabel = newLabel;
});
},
child: Text(buttonLabel),
);
}
}
時間軸
#已於版本中加入:1.16.3
在穩定版中:1.17
參考資料
#API 文件
相關問題
相關 PR
除非另有說明,否則本網站上的文件反映了 Flutter 的最新穩定版本。頁面最後更新於 2024-04-04。 檢視原始碼 或 回報問題。