1

I have a download button in my flutter application that will show Text("download") before button is pressed CircularProgressIndicator() when file is downloading, and Text("Open") when file is downloaded.

_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=>Downloaded
          } else {
            //setState status=>Empty
          }
        });
      } else {
        print("Open");
      }
    },
  );
}

Future<bool> download() async {
  var response = await Future<bool>.delayed(Duration(seconds: 5), () {
    print("Downloading ...");
    return true;
  });
  if (response) {
    print("Downloaded");
    return true;
  } else {
    print("Download Failed!");
    return false;
  }
}

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 status to DOWNLOADED; no problem whatsoever. But if I press download button and then go back, then download() will run in background and when it completes it tries to run one of the setState methods that I've commented out. This either gives error, or says memory leak problem.

I've tried to solve this problem by using isLoaded variable.

@override
void initState() {
  isLoaded = true;
  super.initState();
}
@override
void dispose() {
  isLoaded = false;
  super.dispose();
}

and then checking if isLoaded is true before calling setState method.

if (isLoaded) {
  setState(() {
    status = _FileStatus.DOWNLOADING;
  });
}

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.

1 Answer 1

2

Just add a condition to check whether your state is mounted or not, and when it's not - do not call setState:

          download().then((bool isDownloaded) {
            // Checking if widget is mounted
            if (!mounted) {
              return;
            }

            ...
Sign up to request clarification or add additional context in comments.

5 Comments

this actually solved my initial problem. But I have new problem. After I load second page back again, setState doesn't runs this time as expected and doesn't updates state. So User is stuck seeing downloading... . What is the solution to this? Any idea?
@KshitijDhakal I can't understand your problem without seeing code. What do you mean by "load second page back again"?
originally I needed to call setState to update UI. But the problem was that download() was async so it executed even after screen was already popped from navigator. Now (this isn't really problem) I want to be able to update UI from the same last call to setState from download() after screen has been popped once and then again pushed back again. TLDR; call setState from async function in a page after it has been unmounted and mounted again. I'd really like help in this. If I'm not clear enough we can continue this in chat. I could provide some code.
@KshitijDhakal But when you push a route it should create a new state for it, not use the old one, doesn't it? Because the old one gets disposed after popping. Am I missing something?
you're absolutely right. I'm just trying to implement download button. And want to update button to open when download is completed (It works as long as user remains in the same screen). But as you explained, may be I should change the way I'm tackling this. Thanks anyways.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.