title: How to safely call setState function from async function in flutter?
body: <p>I have a download button in my flutter application that will show <code>Text("download")</code> before button is pressed <code>CircularProgressIndicator()</code> when file is downloading, and <code>Text("Open")</code> when file is downloaded.</p>
  
  <pre><code>_FileStatus status = _FileStatus.EMPTY;
  
  RaisedButton raisedButton() {
    var child;
    if (status == _FileStatus.EMPTY) {
      child = Text("download");
    } else if (status == _FileStatus.DOWNLOADING) {
      child = CircularProgressIndicator();
    } else {
      child = Text("Open");
    }
    return RaisedButton(
      child: child,
      onPressed: () {
        if (status == _FileStatus.EMPTY) {
          setState(() {
            status = _FileStatus.DOWNLOADING;
          });
          download().then((bool isDownloaded) {
            if (isDownloaded) {
              //setState status=&gt;Downloaded
            } else {
              //setState status=&gt;Empty
            }
          });
        } else {
          print("Open");
        }
      },
    );
  }
  
  Future&lt;bool&gt; download() async {
    var response = await Future&lt;bool&gt;.delayed(Duration(seconds: 5), () {
      print("Downloading ...");
      return true;
    });
    if (response) {
      print("Downloaded");
      return true;
    } else {
      print("Download Failed!");
      return false;
    }
  }
  </code></pre>
  
  <p>But this button lies in second page of application. So one might press download button and then go back to first page. Normally if I press download button and then wait for it to complete then setState will update <code>status</code> to <code>DOWNLOADED</code>; no problem whatsoever. But if I press <code>download</code> button and then go back, then <code>download()</code> will run in background and when it completes it tries to run one of the <code>setState</code> methods that I've commented out. This either gives error, or says memory leak problem.</p>
  
  <p>I've tried to solve this problem by using isLoaded variable.</p>
  
  <pre><code>@override
  void initState() {
    isLoaded = true;
    super.initState();
  }
  @override
  void dispose() {
    isLoaded = false;
    super.dispose();
  }
  </code></pre>
  
  <p>and then checking if isLoaded is true before calling setState method.</p>
  
  <pre><code>if (isLoaded) {
    setState(() {
      status = _FileStatus.DOWNLOADING;
    });
  }
  </code></pre>
  
  <p>But this feels like hacky method, and I know there must be a better way to tackle this. I've searched to other similar question but couldn't quite find what I was looking for.</p>