OverlayEntries 和 Routes 的重建最佳化
概述
#此最佳化提高了路由過渡的效能,但可能會暴露您應用中缺失的 setState 呼叫。
背景
#在此更改之前,當一個新的不透明條目新增到 OverlayEntry 之上或從其上方移除時,該 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