问题
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 usingflutter run
- using vscode
Dart Code
extension with actrl/cmd + shift + p
andenable 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