Skip to content

Instantly share code, notes, and snippets.

@callmephil
Created February 2, 2025 23:25
Show Gist options
  • Save callmephil/c859dbdff6b5c886eb7310a0995ce561 to your computer and use it in GitHub Desktop.
Save callmephil/c859dbdff6b5c886eb7310a0995ce561 to your computer and use it in GitHub Desktop.
widget_rebuild_evaluation
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int buildIndex = 0;
ColoredBox2 get colorboxConst {
print('method const: $hashCode');
return const ColoredBox2(key: ValueKey('method const'), color: Colors.red);
}
ColoredBox2 get colorboxConst2 {
print('method not const: $hashCode');
return ColoredBox2(key: ValueKey('method not const'), color: Colors.red);
}
@override
Widget build(BuildContext context) {
print('========= $buildIndex ==========');
print('Parent: $hashCode');
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Column(children: [
colorboxConst,
colorboxConst2,
ColoredBox2(key: ValueKey('not const'), color: Colors.red),
const ColoredBox2(key: ValueKey('const'), color: Colors.red),
RepaintBoundary(
child: TextButton(
onPressed: () {
setState(() {
buildIndex = buildIndex + 1;
});
},
child: Text('Update'),
),
),
]),
),
);
}
}
class ColoredBox2 extends SingleChildRenderObjectWidget {
/// Creates a widget that paints its area with the specified [Color].
const ColoredBox2({required this.color, super.child, super.key});
/// The color to paint the background area with.
final Color color;
@override
RenderObject createRenderObject(BuildContext context) {
print('Create $key ${context.widget.hashCode}');
return _RenderColoredBox(color: color);
}
@override
void updateRenderObject(BuildContext context, RenderObject renderObject) {
print('update $key ${context.widget.hashCode}');
(renderObject as _RenderColoredBox).color = color;
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<Color>('color', color));
}
}
class _RenderColoredBox extends RenderProxyBoxWithHitTestBehavior {
_RenderColoredBox({required Color color})
: _color = color,
super(behavior: HitTestBehavior.opaque);
/// The fill color for this render object.
Color get color => _color;
Color _color;
set color(Color value) {
if (value == _color) {
return;
}
_color = value;
markNeedsPaint();
}
@override
void paint(PaintingContext context, Offset offset) {
print('paint: ${context.hashCode}');
// It's tempting to want to optimize out this `drawRect()` call if the
// color is transparent (alpha==0), but doing so would be incorrect. See
// https://github.com/flutter/flutter/pull/72526#issuecomment-749185938 for
// a good description of why.
if (size > Size.zero) {
context.canvas.drawRect(offset & size, Paint()..color = color);
}
if (child != null) {
context.paintChild(child!, offset);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment