Initializing a future in flutter?

Issue

I would like to run a downloading Future function when opening a page in flutter, however it is being called multiple times.

I would like to implement a solution like the second in this article:

https://flutterigniter.com/future-async-called-multiple-times/

(memoizing the future after initialisation so that the init function is not called multiple times)
however in his solution, he initialises the future like this

Future<String> _future;

this is no longer possible in the current version of dart and I was wondering if there was an equivalent, I have tried using the Late keyword and initializing it to null, neither of which work.

Here is the code currently and how I want it
currently:

class _ARState extends State<AR> {
  
@override
  void initState() {
    super.initState();
    WidgetsBinding.instance?.addPostFrameCallback((_) {
      _downloadFiles();
    });
  }

Future<dynamic> _downloadFiles() async {
// some downloading function that is getting run multiple times ....
}


Widget build(BuildContext context) {
    return FutureBuilder<dynamic>(
      future: _downloadFiles(),
      builder: /// stuff i want built
}

how i want it:

class _ARState extends State<AR> {
  
Future<dynamic> _future;

@override
  void initState() {
    super.initState();
    WidgetsBinding.instance?.addPostFrameCallback((_) {
      _downloadFiles();
    });
  }

Future<dynamic> _downloadFiles() async {
// some downloading function that is getting run multiple times ....
}


Widget build(BuildContext context) {
    return FutureBuilder<dynamic>(
      future: _future,
      builder: /// stuff i want built
}

Thanks for any help!

Solution

One way is to make _future nullable and to make your asynchronous function idempotent by checking if _future is null. If it’s null, do work; if it’s not null, then just return the existing Future.

class _ARState extends State<AR> {
  Future<dynamic>? _future;

  ...

  Future<dynamic> _downloadFiles() {
    Future<dynamic> helper() async {
      // Do actual downloading work here.
    }

    if (_future == null) {
      _future = helper();
    }

    return _future;
  }

  Widget build(BuildContext context) {
    return FutureBuilder<dynamic>(
      future: _downloadFiles(),
      ...
  }
}

Answered By – jamesdlin

Answer Checked By – Katrina (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *