quilkin
quilkin

Reputation: 1427

Flutter : how to return correctly from navigation?

I'm using navigation to go to a new page which downloads a chosen file. But after Navigator.pop() I end up with just a blank white screen.

This is the code, including the button and navigation to the download screen:

@override
Widget build(BuildContext context) {

  return Scaffold(
    appBar: AppBar(
       title: Text(widget.title),
    ),
    body: MyMap(
    ),
    floatingActionButton: FloatingActionButton(
      onPressed: () {
        _navigateToFileDownload(context);
      },
      tooltip: 'New File',
      child: Icon(Icons.add),
    ),
  );
} 
void _navigateToFileDownload(BuildContext context) async {
  final result = await Navigator.push(
    context,
    MaterialPageRoute(
      builder: (context) => Downloader(),
    ));
    setState(() {
      filePath = result;
    });
}

In the download class, for a succesful download I have this:

setState(() {
    downloading = false;
    progress = "Download Completed.";
    path = dirloc + randid.toString() + ".kmz";
    Navigator.pop(context,path);
  });

I can't see any errors in the logcat. The code never reaches setState to set the filePath. What am I missing?

[Edit] full source of the downloader below. Most of this was from another SO answer

Widget doDownload() {
  return MaterialApp(
    title: "File Downloader",
    debugShowCheckedModeBanner: false,
    home: FileDownloader(),
    theme: ThemeData(primarySwatch: Colors.blue),
  );
}
class Downloader extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: doDownload(),

    );
  }
}
class FileDownloader extends StatefulWidget {
  @override
  _FileDownloaderState createState() => _FileDownloaderState();
}

class _FileDownloaderState extends State<FileDownloader> {

  final kmzUrl = "https://quilkin.co.uk/wandrer/cornwall-1.kmz";
  bool downloading = false;
  var progress = "";
  var path = "No Data";
  var platformVersion = "Unknown";
  Permission permission1 = Permission.storage;
  var _onPressed;
  static final Random random = Random();
  Directory externalDir;

  @override
  void initState() {
    super.initState();
    downloadFile();
  }
  Future<void> downloadFile() async {
    Dio dio = Dio();
    if (await Permission.storage.request().isDenied) {
      await Permission.storage.request();
    }
    if (await Permission.storage.status.isGranted) {
      String dirloc = "";
      if (Platform.isAndroid) {
        //dirloc = "/sdcard/download/";
        dirloc = (await getApplicationDocumentsDirectory()).path;
      } else {
        dirloc = (await getApplicationDocumentsDirectory()).path;
      }

      var randid = random.nextInt(10000);

      try {
        FileUtils.mkdir([dirloc]);
        await dio.download(kmzUrl, dirloc + randid.toString() + ".kmz",
            onReceiveProgress: (receivedBytes, totalBytes) {
              setState(() {
                downloading = true;
                progress =
                    ((receivedBytes / totalBytes) * 100).toStringAsFixed(0) + "%";
              });
            });
      } catch (e) {
        print(e);
      }

      setState(() {
        downloading = false;
        progress = "Download Completed.";
        path = dirloc + randid.toString() + ".kmz";
        Navigator.pop(context,path);
      });
    } else {
      setState(() {
        progress = "Permission Denied!";
        _onPressed = () {
          downloadFile();
        };
      });
    }
  }
  @override
  Widget build(BuildContext context) => Scaffold(
      appBar: AppBar(
        title: Text('File Downloader'),
      ),
      body: Center(
          child: downloading
              ? Container(
            height: 120.0,
            width: 200.0,
            child: Card(
              color: Colors.black,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  CircularProgressIndicator(),
                  SizedBox(
                    height: 10.0,
                  ),
                  Text(
                    'Downloading File: $progress',
                    style: TextStyle(color: Colors.white),
                  ),
                ],
              ),
            ),
          )
              : Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(path),
              MaterialButton(
                child: Text('Request Permission Again.'),
                onPressed: _onPressed,
                disabledColor: Colors.black12,
                color: Colors.pink,
                textColor: Colors.white,
                height: 40.0,
                minWidth: 100.0,
              ),
            ],
          )));
}

Upvotes: 0

Views: 97

Answers (1)

D&#225;niel R&#243;zsa
D&#225;niel R&#243;zsa

Reputation: 535

You don't need to call setState if you pop the widget.
You can simply call the .pop(context, path)
If your second class reaches the pop method, it should work.

EDIT: seeing your code:
The problem that you create a second MaterialApp in your Downlaoder class that mess up with the navigator.
You can remove the Downloader class and build the FileDownloader class directly, or instead of MaterialApp use Scaffold in your Downloader class.

Upvotes: 1

Related Questions