StatefulBuilder
A platonic widget that both has state and calls a closure to obtain its child widget.
The StateSetter function passed to the builder is used to invoke a rebuild instead of a typical State's State.setState.
Since the builder is re-invoked when the StateSetter is called, any variables that represents state should be kept outside the builder function.
import 'package:flutter/material.dart'; const Color darkBlue = Color.fromARGB(255, 18, 32, 47); void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData.dark().copyWith( scaffoldBackgroundColor: darkBlue, ), debugShowCheckedModeBanner: false, home: const Scaffold( body: Center( child: MyWidget(), ), ), ); } } class MyWidget extends StatefulWidget { const MyWidget({Key? key}) : super(key: key); @override StatecreateState() => _MyWidgetState(); } class _MyWidgetState extends State { double lerp = 0; Color buttonColor = Colors.blue[100]!; @override Widget build(BuildContext context) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ StatefulBuilder( builder: (context, setState) { return InexpensiveWidget( color: Color.lerp(buttonColor, Colors.black, lerp)!, onPressed: () => setState(() { lerp += 0.1; if (lerp > 1) { lerp = 0; } }), ); }, ), // Pretend `const` is not feasible here // ignore: prefer_const_constructors ExpensiveWidget(), ], ), ); } } class InexpensiveWidget extends StatelessWidget { const InexpensiveWidget({ Key? key, required this.color, required this.onPressed, }) : super(key: key); final VoidCallback onPressed; final Color color; @override Widget build(BuildContext context) { print(" building InexpensiveWidget"); return TextButton( onPressed: onPressed, style: ButtonStyle( backgroundColor: MaterialStateProperty.all(color)), child: const Text("I rebuild often"), ); } } class ExpensiveWidget extends StatelessWidget { const ExpensiveWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context) { print('Painstakingly building ExpensiveWidget'); return const Text("I'm expensive!"); } }