如何在加载文件后执行 Navigator.push 操作(在此过程中使用 CircularProgressIndicator())?

How to implement Navigator.push action after loading file (using CircularProgressIndicator() during the process)?

在显示 CircularProgressIndicator() 并在成功加载文件后使用 Navigator.pushNamedAndRemoveUntil 的同时实现文件后台下载的“最佳实践”方法是什么?

这是我的代码示例:

class Downloader extends StatefulWidget {
  const Downloader({Key? key}) : super(key: key);

  @override
  DownloaderState createState() => DownloaderState();
}

class DownloaderState extends State<Downloader> {
  Future<Directory?>? _appDocumentsDirectory;
  bool _isDownloaded = false;

  @override
  void initState() {
    super.initState();
    _initDownloader();
  }

  _initDownloader() async {
    setState(() {
        _appDocumentsDirectory = getApplicationDocumentsDirectory();
      });
  }

  Future<void> _downloadJson(String localPath) async {
    if ( === WE CHECK FOR CREDENTIALS HERE === ) {
      FTPConnect ftpConnect = FTPConnect(
          BaseAPI.ftpServerAddress,
          port: BaseAPI.ftpServerPort,
          user: _login,
          pass: _passwd);
      try {
        String fileName = 'filename.json';
        String localFileName = localPath + "/filename.json";

        print(" localFileName: $localFileName");

        await ftpConnect.connect();
        await ftpConnect.changeDirectory('ftp');
        bool res = await ftpConnect.downloadFileWithRetry(
            fileName, File(localFileName));
        await ftpConnect.disconnect();

        print("is downloaded? $res");

      } catch (e) {

        print("=== ERROR ===\n${e.toString()}");

      }
      _isDownloaded = true;

    } else {
      _isDownloaded = false;
    }
  }

Widget _buildDirectory(
      BuildContext context, AsyncSnapshot<Directory?> snapshot) {
    Text text = const Text('');
    if (snapshot.connectionState == ConnectionState.done) {
      if (snapshot.hasError) {
        text = Text('Error: ${snapshot.error}');
      } else if (snapshot.hasData) {

        String _s = snapshot.data!.path + "/filename.json";
        String _z = "File downloaded";

        _downloadJson(snapshot.data!.path);    //////////////  <= downloading here

        if (!_isDownloaded) {
          _z = "Failed to download file";
        }
        text = Text('Path to a file: \n$_s\n\npath: \n${snapshot.data!.path}\n\nFile downloaded: $_isDownloaded');

      } else {
        text = const Text('path unavailable');
      }
    }
    return text;
  }

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Loading data"),
        foregroundColor: Colors.black,
        backgroundColor: Colors.redAccent,
      ),
      body: Center(
        child: Column(
              children: <Widget>[
                FutureBuilder<Directory?>(
                  future: _appDocumentsDirectory,
                  builder: _buildDirectory,
/// I need to redirect to another page here
                ),
              ],
            ),
        ),
      );
  }
}

所以我的主要问题是:

  1. 如何正确'catch'下载文件的时刻?我只能在控制台 (Android Studio) 中看到打印“已下载?是的”,但我不明白如何捕捉这一刻和 link 对它的一些操作...

据我了解,工作流程是这样的:

1. initialize the `_appDocumentsDirectory`;
2. on initialization start the `FutureBuilder` logic:

 2.1 - checking if `_appDocumentsDirectory` has data and

 2.2 - calling the `_downloadJson`
  1. 我也可以(或应该)将逻辑包装在 FutureBuilder 的 _downloadJson 函数中吗?

  2. 如果我能以某种方式解决第一个和第二个问题 - 您通常如何在需要时执行所需的 Navigator.pushNamedAndRemoveUntil()

先回答下面的问题,

如何在下载文件的时候显示一个CircularProgressIndicator,可以简单的引入一个变量isDownloading如下,

bool isDownloading = false;

下载时,即

setState(() => isDownloading = true);
bool res = await ftpConnect.downloadFileWithRetry(
        fileName, File(localFileName));
setState(() => isDownloading = false);

因为一旦调用 setState 就会重建主体,在主体中使用类似这样的东西,

Scaffold(
  body: isDownloading ? CircularProgressIndicator() : ..[your code],
);

接下来要获取本地推送通知,您可以简单地使用 flutter_local_notifications: ^9.5.3+1

这绝对可以解决问题