Flutter : How to Debug which widgets re-rendered on state change

杀马特。学长 韩版系。学妹 提交于 2021-02-07 19:56:25

问题


I am using Redux with Flutter for state management. Whenever I dispatch an action, I want to know which widgets were re-rendered. Is there any way of doing it?


回答1:


In flutter, whenever one widget update ; the whole widget tree repaint. So... no.

But you can also introduce "repaint boundaries" manually by inserting in your tree a RepaintBoundary widget. This explicitly tells flutter to create a new painting layer for it's child (which implies memory cache). So that whenever that child updates, it won't repaint it's parent too.

What you can do is instead debug when a repaintboundary is repainted.

For this you can enable repaint rainbow by :

  • pressing t when using flutter run
  • using vscode Dart Code extension with a ctrl/cmd + shift + p and enable repaint rainbow



回答2:


The best way to debug your application to see what widgets is re-rendered is by inserting break points in your code. I would recommend putting a breakpoint within the Widget build(BuildContext context) method.

Alternatively you could also use print statements to make sure the build method is being called.




回答3:


One thing to note first about rendering: rebuilding and repainting are not the same. Rebuilding involves layout and painting, whereas repainting doesn't involve relayout.

How to check for rebuild

Add a print statement in any build methods that you are interested in.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print('MyApp building');                 <-- this
    return MaterialApp(...

And this:

class MyWidget extends StatelessWidget {
  const MyWidget({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    print('MyWidget building');  //         <-- here 
    return ProgressBar(...

If you notice that there are unnecessary parts of your widget tree getting rebuilt, then the solution is to extract out the parts of the tree that are changing into their own widgets, preferably const widgets.

How to check for repainting

To see what is getting repainted, you can use the Dart DevTools. While you app is running, click the Repaint Rainbow button.

Alternatively, you can use the following flag in your code:

void main() {
  debugRepaintRainbowEnabled = true;  //   <-- set this flag to true
  runApp(MyApp());
} 

The regions that are being repainted have a rainbow border that changes colors on each repaint. As you can see in the animation below, the entire window is getting repainted every time. (The blue line in the center is part of the widget, not the repaint rainbow.)

If you want to limit what is getting painted, you can add a RepaintBoundary widget to your tree like this:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print('MyApp building');
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Container(
            child: RepaintBoundary(  //   <-- repaint boundary
              child: ProgressBar(
                barColor: Colors.blue,
                thumbColor: Colors.red,
                thumbSize: 20.0,
              ),
            ),
          ),
        ),
      ),
    );
  }
}

Now when you use DevTools and select the Repaint Rainbow button, you'll see that only the ProgressBar widget is getting repainted.

If the repaint is not expensive, then this is probably not something you need to worry about. At least in most of the documentation that I've seen, people say to minimize rebuilds, but hardly anyone suggests adding repaint boundaries. I'd check the timeline and performance in DartDev tools to see if you need it. Check out the linked video below for details.

See also:

  • RepaintBoundary docs
  • Improve your Flutter Apps performance with a RepaintBoundary


来源:https://stackoverflow.com/questions/50324893/flutter-how-to-debug-which-widgets-re-rendered-on-state-change

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!