Created
March 20, 2025 23:53
-
-
Save s0nerik/bf694393f6c91f7cdb33b269e1f6a521 to your computer and use it in GitHub Desktop.
Flutter widget rebuilds: const vs cached instance vs no caching
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
import 'package:flutter/scheduler.dart'; | |
void main() => runApp(const MyApp()); | |
class MyApp extends StatelessWidget { | |
const MyApp({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
title: 'Flutter Demo', | |
debugShowCheckedModeBanner: false, | |
home: const HomePage(), | |
); | |
} | |
} | |
class HomePage extends StatefulWidget { | |
const HomePage({super.key}); | |
@override | |
State<HomePage> createState() => _HomePageState(); | |
} | |
class _HomePageState extends State<HomePage> { | |
int _counter = 0; | |
bool _useConstChild = false; | |
bool _useCachedChild = false; | |
late Widget _cachedChild; | |
void initState() { | |
super.initState(); | |
_cachedChild = Counter(counter: 0); | |
} | |
void _incrementCounter() { | |
setState(() { | |
_counter += 1; | |
_cachedChild = Counter(counter: _counter); | |
}); | |
} | |
void _rebuild() { | |
setState(() {}); | |
} | |
@override | |
Widget build(BuildContext context) { | |
final widgetCachingType = | |
_useConstChild | |
? 'const' | |
: _useCachedChild | |
? 'cached instance' | |
: 'none'; | |
return Scaffold( | |
body: Center( | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
spacing: 16, | |
children: [ | |
if (_useConstChild) | |
const Counter(counter: -1) | |
else if (_useCachedChild) | |
_cachedChild | |
else | |
Counter(counter: _counter), | |
FilledButton( | |
onPressed: _incrementCounter, | |
child: Text('Increment'), | |
), | |
FilledButton( | |
onPressed: _rebuild, | |
child: Text('Rebuild the HomePage'), | |
), | |
FilledButton( | |
onPressed: | |
() => setState(() { | |
_useConstChild = true; | |
_useCachedChild = false; | |
}), | |
child: Text('Use const child'), | |
), | |
FilledButton( | |
onPressed: | |
() => setState(() { | |
_useConstChild = false; | |
_useCachedChild = true; | |
}), | |
child: Text('Use cached child'), | |
), | |
FilledButton( | |
onPressed: | |
() => setState(() { | |
_useConstChild = false; | |
_useCachedChild = false; | |
}), | |
child: Text('Don\'t use any widget caching'), | |
), | |
Text('Widget caching: ${widgetCachingType}'), | |
], | |
), | |
), | |
); | |
} | |
} | |
class Counter extends StatelessWidget { | |
const Counter({super.key, required this.counter}); | |
final int counter; | |
@override | |
Widget build(BuildContext context) { | |
SchedulerBinding.instance.addPostFrameCallback((_) { | |
ScaffoldMessenger.of(context).showSnackBar( | |
SnackBar( | |
content: Text("Counter rebuilt with value: $counter"), | |
duration: Duration(seconds: 1), | |
), | |
); | |
}); | |
return Text('$counter', style: Theme.of(context).textTheme.headlineMedium); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment