Here is a very simple Flutter Material "app", with a counter that is displayed in a Text widget, and can be incremented by pressing a floating action button, and copied to the clipboard using an action button in the appbar.
The "straightforward" way to implement this (also implemented in the sample code created by the flutter create command), is to define the state at the home page level (MyHomePage and _MyHomePageState classes). This lets the FloatingActionButton and the AppBar action button easily modify and access the _counter state variable, because they are under the Home Page in the widget tree.
However, this means that any change in the _counter state variable will trigger a redraw/rebuild of the entire home page, including the AppBar and the FloatingActionButton, which do not change.
I would like to move the StatefulWidget at the level of the Text Widget that displays the _counter state variable, that is the only widget that actually changes based on state.
But in this case I don't know the ways (or the best way) to let the AppBar Action button and the FloatingActionButton continue to access and modify the _counter state variable.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Hello Counter',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Hello Counter'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.content_copy),
tooltip: 'Copy to Clipboard',
// Get counter by accessing state
onPressed: () => Clipboard.setData(ClipboardData(text: '$_counter')),
)
],
),
body: Center(
child: Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
),
floatingActionButton: FloatingActionButton(
// Set counter by changing state
onPressed: () => setState(() => _counter++),
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}