Various refresh widgets in Flutter

1.FutureBuilder

Very useful widget for handling asynchronous operations and building interfaces. It is typically used with Future objects to build the interface after an asynchronous operation has completed.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {<!-- -->
  @override
  Widget build(BuildContext context) {<!-- -->
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {<!-- -->
  Future<String> fetchData() async {<!-- -->
    // Simulate asynchronous operations, such as requesting data from the network
    await Future.delayed(Duration(seconds: 2));
    return "Hello, World!";
  }

  @override
  Widget build(BuildContext context) {<!-- -->
    return Scaffold(
      appBar: AppBar(
        title: Text("FutureBuilder Example"),
      ),
      body: FutureBuilder<String>(
        future: fetchData(),
        builder: (BuildContext context, AsyncSnapshot<String> snapshot) {<!-- -->
          if (snapshot.connectionState == ConnectionState.waiting) {<!-- -->
            return Center(child: CircularProgressIndicator());
          } else if (snapshot.hasError) {<!-- -->
            return Center(child: Text("Error: ${<!-- -->snapshot.error}"));
          } else {<!-- -->
            return Center(child: Text("Data: ${<!-- -->snapshot.data}"));
          }
        },
      ),
    );
  }
}

If a FutureBuilder is rebuilt frequently while building, it can cause performance issues. Make sure not to nest a FutureBuilder inside a frequently rebuilt widget to avoid unnecessary performance overhead.

2.StreamController

To implement streaming refresh, you usually need to use Stream and StreamBuilder to listen and update data.

import 'dart:async';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {<!-- -->
  @override
  Widget build(BuildContext context) {<!-- -->
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {<!-- -->
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {<!-- -->
  StreamController<int> _dataStreamController = StreamController<int>();
  int_data = 0;

  @override
  void initState() {<!-- -->
    super.initState();
    // Simulate a data source and generate new data every second
    Timer.periodic(Duration(seconds: 1), (timer) {<!-- -->
      _dataStreamController.sink.add(_data + + );
    });
  }

  @override
  void dispose() {<!-- -->
    _dataStreamController.close(); // Close the stream
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {<!-- -->
    return Scaffold(
      appBar: AppBar(
        title: Text("StreamBuilder Example"),
      ),
      body: StreamBuilder<int>(
        stream: _dataStreamController.stream,
        builder: (BuildContext context, AsyncSnapshot<int> snapshot) {<!-- -->
          if (snapshot.connectionState == ConnectionState.waiting) {<!-- -->
            return Center(child: CircularProgressIndicator());
          } else if (snapshot.hasError) {<!-- -->
            return Center(child: Text("Error: ${<!-- -->snapshot.error}"));
          } else {<!-- -->
            return Center(child: Text("Data: ${<!-- -->snapshot.data}"));
          }
        },
      ),
    );
  }
}

3.ValueListenableBuilder

Used to monitor value changes of ValueListenable objects and build interfaces. It allows you to update the interface when values change without rebuilding the entire widget tree.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class CounterModel extends ValueNotifier<int> {<!-- -->
  CounterModel(int value) : super(value);
}

class MyApp extends StatelessWidget {<!-- -->
  @override
  Widget build(BuildContext context) {<!-- -->
    final counterModel = CounterModel(0);

    return MaterialApp(
      home:Scaffold(
        appBar: AppBar(
          title: Text('ValueListenableBuilder Example'),
        ),
        body: Center(
          child: ValueListenableBuilder<int>(
            valueListenable: counterModel,
            builder: (BuildContext context, int value, Widget child) {<!-- -->
              return Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text('Counter Value: $value'),
                  ElevatedButton(
                    onPressed: () {<!-- -->
                      counterModel.value + + ;
                    },
                    child: Text('Increment'),
                  ),
                ],
              );
            },
          ),
        ),
      ),
    );
  }
}

4.LayoutBuilder

Used to obtain the constraint information of the parent widget and customize the build interface based on the constraint information. It is often used to create widgets that dynamically adjust based on parent dimensions, such as adaptive layouts.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {<!-- -->
  @override
  Widget build(BuildContext context) {<!-- -->
    return MaterialApp(
      home:Scaffold(
        appBar: AppBar(
          title: Text('LayoutBuilder Example'),
        ),
        body: Center(
          child: Container(
            color: Colors.blue,
            width: 200.0,
            height: 200.0,
            child: LayoutBuilder(
              builder: (BuildContext context, BoxConstraints constraints) {<!-- -->
                return Center(
                  child: Text(
                    'Width: ${<!-- -->constraints.maxWidth.toStringAsFixed(2)}\
Height: ${<!-- -->constraints.maxHeight.toStringAsFixed(2)}',
                    style: TextStyle(color: Colors.white),
                  ),
                );
              },
            ),
          ),
        ),
      ),
    );
  }
}

5.AnimatedBuilder

A widget used to listen for value changes during animation execution and build the interface. Typically, it is used with an AnimationController or other animation object to update the interface during animation execution.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {<!-- -->
  @override
  Widget build(BuildContext context) {<!-- -->
    return MaterialApp(
      home:Scaffold(
        appBar: AppBar(
          title: Text('AnimatedBuilder Example'),
        ),
        body: Center(
          child: MyAnimationWidget(),
        ),
      ),
    );
  }
}

class MyAnimationWidget extends StatefulWidget {<!-- -->
  @override
  _MyAnimationWidgetState createState() => _MyAnimationWidgetState();
}

class _MyAnimationWidgetState extends State<MyAnimationWidget>
    with SingleTickerProviderStateMixin {<!-- -->
  AnimationController _controller;
  Animation<double> _animation;

  @override
  void initState() {<!-- -->
    super.initState();

    _controller = AnimationController(
      vsync: this,
      duration: Duration(seconds: 2),
    );

    _animation = Tween(begin: 0.0, end: 1.0).animate(_controller)
      ..addListener(() {<!-- -->
        //Rebuild the interface when the animation value changes
        setState(() {<!-- -->});
      });

    _controller.forward();
  }

  @override
  void dispose() {<!-- -->
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {<!-- -->
    return AnimatedBuilder(
      animation: _controller,
      builder: (BuildContext context, Widget child) {<!-- -->
        returnOpacity(
          opacity: _animation.value,
          child: Container(
            color: Colors.blue,
            width: 200.0,
            height: 200.0,
            child: Center(
              child: Text(
                'Opacity: ${<!-- -->_animation.value.toStringAsFixed(2)}',
                style: TextStyle(color: Colors.white),
              ),
            ),
          ),
        );
      },
    );
  }
}

6.PageRouteBuilder

Widget for customizing page transition animations, typically used with Navigator. It allows you to create customized page switching effects, including sliding, gradient, zoom and other animation effects.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {<!-- -->
  @override
  Widget build(BuildContext context) {<!-- -->
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {<!-- -->
  @override
  Widget build(BuildContext context) {<!-- -->
    return Scaffold(
      appBar: AppBar(
        title: Text('PageRouteBuilder Example'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {<!-- -->
            Navigator.of(context).push(
              PageRouteBuilder(
                pageBuilder: (context, animation, secondaryAnimation) {<!-- -->
                  return SecondPage();
                },
                transitionsBuilder: (context, animation, secondaryAnimation, child) {<!-- -->
                  const begin = Offset(1.0, 0.0);
                  const end = Offset.zero;
                  const curve = Curves.easeInOut;
                  var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));
                  var offsetAnimation = animation.drive(tween);
                  return SlideTransition(
                    position: offsetAnimation,
                    child: child,
                  );
                },
              ),
            );
          },
          child: Text('Go to Second Page'),
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {<!-- -->
  @override
  Widget build(BuildContext context) {<!-- -->
    return Scaffold(
      appBar: AppBar(
        title: Text('Second Page'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {<!-- -->
            Navigator.of(context).pop();
          },
          child: Text('Back to First Page'),
        ),
      ),
    );
  }
}

7.AnimatedSwitcher

A widget for performing animations when switching between different widgets. It allows you to apply custom entry and exit animation effects when switching widgets.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {<!-- -->
  @override
  Widget build(BuildContext context) {<!-- -->
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {<!-- -->
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {<!-- -->
  bool _showFirstWidget = true;

  void _toggleWidget() {<!-- -->
    setState(() {<!-- -->
      _showFirstWidget = !_showFirstWidget;
    });
  }

  @override
  Widget build(BuildContext context) {<!-- -->
    return Scaffold(
      appBar: AppBar(
        title: Text('AnimatedSwitcher Example'),
      ),
      body: Center(
        child: AnimatedSwitcher(
          duration: Duration(milliseconds: 500), // The duration of the switching animation
          child: _showFirstWidget
              ?FirstWidget(
                  key: ValueKey<int>(1), //Specify different keys to distinguish different widgets
                )
              : SecondWidget(
                  key: ValueKey<int>(2), //Specify different keys to distinguish different widgets
                ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _toggleWidget,
        child: Icon(Icons.swap_horiz),
      ),
    );
  }
}

class FirstWidget extends StatelessWidget {<!-- -->
  FirstWidget({<!-- -->Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {<!-- -->
    return Container(
      key: key,
      width: 200,
      height: 200,
      color: Colors.blue,
      child: Center(
        child: Text(
          'First Widget',
          style: TextStyle(color: Colors.white),
        ),
      ),
    );
  }
}

class SecondWidget extends StatelessWidget {<!-- -->
  SecondWidget({<!-- -->Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {<!-- -->
    return Container(
      key: key,
      width: 200,
      height: 200,
      color: Colors.green,
      child: Center(
        child: Text(
          'Second Widget',
          style: TextStyle(color: Colors.white),
        ),
      ),
    );
  }
}

8.FormBuilder

FormBuilder is a Flutter plugin that simplifies the creation and processing of forms. It makes form management easier by creating form fields and validation logic.

dependencies:
  flutter_form_builder: ^9.1.1
final GlobalKey<FormBuilderState> _formKey = GlobalKey<FormBuilderState>();

@override
Widget build(BuildContext context) {<!-- -->
  return Scaffold(
    appBar: AppBar(
      title: Text('Login Form'),
    ),
    body:Padding(
      padding: const EdgeInsets.all(16.0),
      child: FormBuilder(
        key: _formKey,
        autovalidateMode: AutovalidateMode.always, // Automatic verification mode
        child: Column(
          children: <Widget>[
            FormBuilderTextField(
              name: 'username',
              decoration: InputDecoration(labelText: 'Username'),
              validator: FormBuilderValidators.required(context),
            ),
            FormBuilderTextField(
              name: 'password',
              decoration: InputDecoration(labelText: 'Password'),
              validator: FormBuilderValidators.required(context),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {<!-- -->
                if (_formKey.currentState.saveAndValidate()) {<!-- -->
                  // Form verification passes, perform submission operation
                  print(_formKey.currentState.value);
                }
              },
              child: Text('Submit'),
            ),
          ],
        ),
      ),
    ),
  );
}