Skip to content

Instantly share code, notes, and snippets.

@Mastersam07
Last active March 27, 2024 19:41
Show Gist options
  • Select an option

  • Save Mastersam07/65b822ea7bf3bc87b099d1fec59c7745 to your computer and use it in GitHub Desktop.

Select an option

Save Mastersam07/65b822ea7bf3bc87b099d1fec59c7745 to your computer and use it in GitHub Desktop.
Future controller idea
import 'package:flutter/material.dart';
typedef FutureGenerator<T> = Future<T> Function();
class FutureController<T> {
Future<T>? _future;
VoidCallback? _onUpdate;
final FutureGenerator<T>? _futureGenerator;
FutureController({FutureGenerator<T>? futureGenerator})
: _futureGenerator = futureGenerator {
// Generate the initial future if a generator is provided
if (_futureGenerator != null) {
_future = _futureGenerator();
}
}
Future<T>? get future => _future;
void refresh() {
if (_futureGenerator != null) {
_future = _futureGenerator();
_notifyListeners();
}
}
void _notifyListeners() {
_onUpdate?.call();
}
void addListener(VoidCallback onUpdate) {
_onUpdate = onUpdate;
// If the future is not set, generate and notify listeners immediately.
if (_future == null && _futureGenerator != null) {
_future = _futureGenerator();
_notifyListeners();
}
}
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: MyFutureBuilderWidget(),
);
}
}
class MyFutureBuilderWidget extends StatefulWidget {
@override
_MyFutureBuilderWidgetState createState() => _MyFutureBuilderWidgetState();
}
class _MyFutureBuilderWidgetState extends State<MyFutureBuilderWidget> {
late FutureController<String> futureController;
@override
void initState() {
super.initState();
futureController = FutureController<String>(
futureGenerator: fetchData, // Provide the future generator
);
// Add listener to rebuild when future updates
futureController.addListener(() {
setState(() {});
});
}
Future<String> fetchData() async {
await Future.delayed(Duration(seconds: 5));
return 'Data Loaded';
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('FutureController with FutureBuilder')),
body: FutureBuilder<String>(
future: futureController.future,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
}
if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
}
return Center(child: Text(snapshot.data ?? 'No data'));
},
),
floatingActionButton: FloatingActionButton(
onPressed: () => futureController.refresh(),
child: Icon(Icons.refresh),
),
);
}
}
@Mastersam07
Copy link
Author

Using a ValueNotifier

import 'package:flutter/material.dart';

typedef FutureGenerator<T> = Future<T> Function();

class FutureController<T> extends ValueNotifier<Future<T>?> {
  final FutureGenerator<T> _generator;

  FutureController(this._generator) : super(null) {
    refresh(); // Automatically load initial future
  }

  void refresh() {
    value = _generator();
    notifyListeners();
  }
}

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: MyFutureBuilderWidget(),
    );
  }
}

class MyFutureBuilderWidget extends StatefulWidget {
  @override
  _MyFutureBuilderWidgetState createState() => _MyFutureBuilderWidgetState();
}

class _MyFutureBuilderWidgetState extends State<MyFutureBuilderWidget> {
  late FutureController<String> _futureNotifier;

  @override
  void initState() {
    super.initState();
    // Initialize the notifier with the fetchData method.
    _futureNotifier = FutureController<String>(fetchData);
  }

  Future<String> fetchData() async {
    await Future.delayed(Duration(seconds: 5)); // Simulate a network delay
    return "Data Loaded";
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('FutureController with FutureBuilder')),
      body: ValueListenableBuilder<Future<String>?>(
        valueListenable: _futureNotifier,
        builder: (context, future, child) {
          return FutureBuilder<String>(
            future: future,
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.waiting) {
                return Center(child: CircularProgressIndicator());
              }
              if (snapshot.hasError) {
                return Center(child: Text('Error: ${snapshot.error}'));
              }
              return Center(child: Text(snapshot.data ?? 'No data'));
            },
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () =>
            _futureNotifier.refresh(),
        child: Icon(Icons.refresh),
      ),
    );
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment