如何解决如何防止带有回调的子树在 Flutter 中重新渲染?
我是 Flutter 的新手,有一些性能问题。对于我的应用程序,我创建了一个自定义侧边栏菜单,灵感来自
为此,我创建了一个作为父屏幕的有状态顶级小部件。它包含一个 Stack
小部件,按钮上有导航屏幕,顶部有一个内容屏幕。用户应该能够通过两种方式打开/关闭菜单:
为了满足第 2 点,我在父屏幕上添加了一个 GestureDetector
,以便在整个屏幕中检测到滑动,从而在全视图中将内容屏幕动画化到侧面/背面。为了满足第 1 点,我将 onPress
回调传递给内容屏幕(将其传递给汉堡 iconButton),它也执行顶级动画。但是,阅读文档 (stateful performance considerations) 时,随着重建的进行,这种顶级有状态小部件似乎对性能有害。由于回调,我无法使我的内容屏幕成为 const
小部件(这是建议的解决方案)。这显然是次优的,因为在内容屏幕中,只有图标在菜单打开时有动画变化(图标从汉堡变成箭头)。
如何最小化子树中的重新渲染次数?有没有办法将屏幕作为 const
小部件传递,即使它有回调?或者目前的方法是否令人满意?
我目前拥有的代码如下:
class ParentScreen extends StatefulWidget {
const ParentScreen({Key? key}) : super(key: key);
@override
_ParentScreenState createState() => _ParentScreenState();
}
class _ParentScreenState extends State<ParentScreen> {
bool isMenuOpen = false;
double xOffset = 0;
double yOffset = 0;
double rotationAngle = 0;
double scaleFactor = 1;
double toradians(double degrees) => degrees * math.pi / 180.0;
void animateMenu() {
setState(() {
...
isMenuOpen = !isMenuOpen;
});
}
@override
Widget build(BuildContext context) {
return SafeArea(
// Detect user swipe to navigate between the screens
child: GestureDetector(
onHorizontalDragEnd: (DragEndDetails details) {
if (details.primaryVeLocity != null) {
if (details.primaryVeLocity! > 0) {
// Right swipe,close menu if open
if (isMenuOpen) animateMenu();
} else if (details.primaryVeLocity! < 0) {
// Left swipe,open menu if closed
if (!isMenuOpen) animateMenu();
}
}
},child: Scaffold(
body: Stack(
children: <Widget>[
const DrawerScreen(),// Screen with navigation information
AnimatedContainer(
transform: Matrix4.translationValues(xOffset,yOffset,0)
..scale(scaleFactor)
..rotateZ(toradians(rotationAngle)),duration: const Duration(milliseconds: 300),child: HomeScreen( // Screen with custom content
onMenuPress: animateMenu,),],);
}
}
解决方法
好吧,您不需要使父小部件成为有状态的小部件。
首先制作实际菜单,包括它的动画,它位于小部件上,该小部件会覆盖其他所有内容..(类似于您在 Stack
小部件中所说的内容)。
然后创建一个位于小部件树之外的对象(通常在 flutter-world 中称为 BLoC) - ChangeNotifier
或 Stream
并将其注入无状态小部件(最简单的方法是使用provider
包,但您也可以使用 InheritedWidget
。
当你想显示菜单时,你只需改变这个外部对象的状态,它会通知菜单小部件展开。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。