【问题标题】:Flutter - Image.memory not refreshing after source changeFlutter - Image.memory 在源更改后不刷新
【发布时间】:2021-11-27 11:22:02
【问题描述】:

我有一个允许用户上传文档(作为图像)的页面。我的页面结构是,对于可以上传的每种文档类型,使用 Document_Upload 小部件来减少重复代码的数量。

在初始加载时,我使用 FutureBuilder 获取用户已经从我们的 REST Api 上传的所有文档,然后使用相关数据填充每个 Document_Upload 小部件。

成功上传后,我们的 REST Api 将新图像作为字节数组返回到 Flutter 应用程序,以便显示。

我目前面临的问题是,无论我尝试什么,图像小部件 (Image.memory) 都不会显示新图像,它只会停留在旧图像上。 我已经尝试了几乎所有我能想到/在网上找到的方法来解决这个问题,包括:

  • 调用 setState({});更新 imageString 变量后 - 我可以看到小部件闪烁,但它仍保留在原始图像上。
  • 使用函数回调父窗口小部件以重建整个子窗口小部件树 - 结果与 setState 相同,所有窗口小部件闪烁,但没有更新。
  • 在更新 imageString 之前调用 imageCache.clear() 和 imageCache.clearLiveImages()。
  • 使用 CircleAvatar 代替 Image.memory。
  • 通过在 setState 调用中调用 new Image.memory() 来重建 Image 小部件。

我开始怀疑这是否与 Image.memory 本身有关,但是,使用 Image.File / Image.network 不是我们当前要求的选项。

手动刷新页面会显示新图像。

我的代码如下:

documents_page.dart

class DocumentsPage extends StatefulWidget {
  @override
  _DocumentsPageState createState() => _DocumentsPageState();
}

class _DocumentsPageState extends State<DocumentsPage>
    with SingleTickerProviderStateMixin {
  Future<Personal> _getUserDocuments;
  Personal _documents;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _getUserDocuments = sl<AccountProvider>().getUserDocuments();
  }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: SafeArea(
        child: Center(
            child: Padding(
          padding: EdgeInsets.all(20),
          child: Container(
              constraints: BoxConstraints(maxWidth: 1300),
              child: buildFutureBuilder(context)),
        )),
      ),
    );
  }

  Widget buildFutureBuilder(BuildContext context) {
    var screenSize = MediaQuery.of(context).size;
    return FutureBuilder<Personal>(
        future: _getUserDocuments,
        builder: (context, AsyncSnapshot<Personal> snapshot) {
          if (!snapshot.hasData) {
            return Text("Loading");
          } else {
            if (snapshot.data == null) {
              return Center(child: Text('Error: ${snapshot.error}'));
            } else {
              _documents = snapshot.data;

              return Column(
                children: [
                  SizedBox(height: 20.0),
                  Text(
                    "DOCUMENTS",
                    textAlign: TextAlign.center,
                    style: TextStyle(
                        fontSize: 25,
                        fontWeight: FontWeight.bold,
                        color: AppColors.navy),
                  ),
                  Container(
                    constraints: BoxConstraints(maxWidth: 250),
                    child: Divider(
                      color: AppColors.darkBlue,
                      height: 20,
                    ),
                  ),
                  Container(
                      margin: EdgeInsets.only(top: 5.0, bottom: 5.0),
                      child: Text(
                          "These documents are required in order to verify you as a user",
                          style: TextStyle(fontSize: 14))),
                  Container(
                      margin: EdgeInsets.only(bottom: 25.0),
                      child: Text("View our Privacy Policy",
                          style: TextStyle(fontSize: 14))),
                  Container(
                      child: screenSize.width < 768
                          ? Column(
                              children: [
                                DocumentUpload(
                                    imageType: "ID",
                                    imageString: _documents.id),
                                DocumentUpload(
                                  imageType: "Drivers License Front",
                                  imageString: _documents.driversLicenseFront,
                                ),
                                DocumentUpload(
                                  imageType: "Drivers License Back",
                                  imageString: _documents.driversLicenseBack,
                                )
                              ],
                            )
                          : Row(
                              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                              children: [
                                  DocumentUpload(
                                      imageType: "ID",
                                      imageString: _documents.id),
                                  DocumentUpload(
                                    imageType: "Drivers License Front",
                                    imageString: _documents.driversLicenseFront,
                                  ),
                                  DocumentUpload(
                                    imageType: "Drivers License Back",
                                    imageString: _documents.driversLicenseBack,
                                  ),
                                ])),
                  Container(
                      child: screenSize.width < 768
                          ? Container()
                          : Padding(
                              padding:
                                  EdgeInsets.only(top: 10.0, bottom: 10.0))),
                  Container(
                      child: screenSize.width < 768
                          ? Column(
                              children: [
                                DocumentUpload(
                                  imageType: "Selfie",
                                  imageString: _documents.selfie,
                                ),
                                DocumentUpload(
                                  imageType: "Proof of Residence",
                                  imageString: _documents.proofOfResidence,
                                ),
                                Container(width: 325)
                              ],
                            )
                          : Row(
                              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                              children: [
                                  DocumentUpload(
                                    imageType: "Selfie",
                                    imageString: _documents.selfie,
                                  ),
                                  DocumentUpload(
                                    imageType: "Proof of Residence",
                                    imageString: _documents.proofOfResidence,
                                  ),
                                  Container(width: 325)
                                ])),
                ],
              );
            }
          }
        });
  }
}

document_upload.dart

class DocumentUpload extends StatefulWidget {
  final String imageType;
  final String imageString;

  const DocumentUpload({this.imageType, this.imageString});

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

class _DocumentUploadState extends State<DocumentUpload> {
  String _imageType;
  String _imageString;
  bool uploadPressed = false;
  Image _imageWidget;

  @override
  Widget build(BuildContext context) {
    setState(() {
      _imageType = widget.imageType;
      _imageString = widget.imageString;

      _imageWidget =
          new Image.memory(base64Decode(_imageString), fit: BoxFit.fill);
    });

    return Container(
        constraints: BoxConstraints(maxWidth: 325),
        height: 200,
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(20),
          boxShadow: [
            new BoxShadow(
              color: AppColors.lightGrey,
              blurRadius: 5.0,
              offset: Offset(0.0, 3.0),
            ),
          ],
        ),
        child: Card(
            color: Colors.white,
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(20.0),
            ),
            child: Column(children: <Widget>[
              Padding(padding: EdgeInsets.only(top: 5.0)),
              Row(
                //ROW 1
                children: <Widget>[
                  Expanded(
                    child: Text(
                      _imageType,
                      textAlign: TextAlign.center,
                      style: TextStyle(
                          fontSize: 18,
                          fontWeight: FontWeight.bold,
                          color: AppColors.darkBlue),
                    ),
                  ),
                ],
              ),
              Row(
                //ROW 2
                children: <Widget>[
                  Expanded(
                    child: Container(
                        padding: EdgeInsets.only(left: 5.0, bottom: 5.0),
                        child: ClipRRect(
                          borderRadius: BorderRadius.circular(20.0),
                          child: _imageWidget,
                        )),
                  ),
                  Consumer<AccountProvider>(
                      builder: (context, provider, child) {
                    return Padding(
                        padding: EdgeInsets.all(10.0),
                        child: Column(
                            mainAxisAlignment: MainAxisAlignment.spaceBetween,
                            children: <Widget>[
                              Padding(
                                  padding:
                                      EdgeInsets.only(top: 5.0, bottom: 5.0),
                                  child: Icon(Icons.star,
                                      size: 20, color: AppColors.darkBlue)),
                              Padding(
                                  padding:
                                      EdgeInsets.only(top: 5.0, bottom: 5.0),
                                  child: Text('Drag file here or',
                                      textAlign: TextAlign.center)),
                              Padding(
                                  padding:
                                      EdgeInsets.only(top: 5.0, bottom: 5.0),
                                  child: DynamicGreyButton(
                                    title: uploadPressed
                                        ? "Uploading ..."
                                        : "Browse",
                                    onPressed: () async {
                                      FilePickerResult result =
                                          await FilePicker.platform.pickFiles(
                                              type: FileType.custom,
                                              allowedExtensions: [
                                            'jpg',
                                            'jpeg',
                                            'png'
                                          ]);
                                      if (result != null) {
                                        uploadPressed = true;
                                        Uint8List file =
                                            result.files.single.bytes;
                                        String fileType =
                                            result.files.single.extension;

                                        await provider
                                            .doUploadDocument(
                                                _imageType, file, fileType)
                                            .then((uploadResult) {
                                          if (uploadResult == null ||
                                              uploadResult == '') {
                                            showToast(
                                                "Document failed to upload");
                                            return;
                                          } else {
                                            showToast("Document uploaded",
                                                Colors.green, "#66BB6A");
                                            uploadPressed = false;
                                            _imageString = uploadResult;
                                            setState(() {});
                                          }
                                        });
                                      } else {
                                        // User canceled the picker
                                        uploadPressed = false;
                                      }
                                    },
                                  ))
                            ]));
                  })
                ],
              ),
            ])));
  }
}

图片上传 HTTP 调用

  @override
  Future uploadDocuments(DocumentsUpload model) async {
    final response = await client.post(
        Uri.https(appConfig.baseUrl, "/api/Account/PostDocuments_Flutter"),
        body: jsonEncode(model.toJson()),
        headers: <String, String>{
          'Content-Type': 'application/json'
        });

    if (response.statusCode == 200) {
      var data = json.decode(response.body);
      return data;
    } else {
      return "";
    }
  }

编辑:附上当前行为的 GIF。

在这一点上我几乎没有想法,任何帮助将不胜感激。

【问题讨论】:

    标签: flutter dart widget flutter-web


    【解决方案1】:

    想出了一个解决方案。 我创建了第二个变量来保存新的图像字符串,并在第二个变量具有值后显示一个全新的图像小部件。

    String _newImage;
    

    在上传成功...

    _newImage = uploadResult;
    setState(() {});
    

    图像小部件...

    child: (_newImage == null || _newImage == '')
             ? new Image.memory(base64Decode(_imageString), fit: BoxFit.fill)
             : new Image.memory(base64Decode(_newImage), fit: BoxFit.fill)
    

    不是一个非常优雅的解决方案,但它是一个解决方案,但也不一定是原始问题为何存在的答案。

    【讨论】:

      猜你喜欢
      • 2013-01-05
      • 2012-04-01
      • 2013-09-16
      • 2016-05-07
      • 2016-08-04
      • 2013-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多