尝试在flutter中跨异步间隙使用构建上下文

问题描述 投票:0回答:1

我正在尝试构建一个聊天应用程序,并将此类称为 ChatBubble。这还能够从主题列表中进行分类。 这是我的代码:

class _ChatBubbleState extends State<ChatBubble> {
  final topicsDb = TopicsDatabase();
  // Copy text to clipboard
  void _copyToClipboard(String text) {...

  final GlobalKey _key = GlobalKey();

  @override
  Widget build(BuildContext context) {
    //bool isDarkMode = Theme.of(context).brightness == Brightness.dark;
    // get the Topic object using the topicId of the note
    Topic? topic = widget.note.topicId != null
        ? topicsDb.getTopicById(widget.note.topicId!)
        : null;

    double maxWidth = MediaQuery.of(context).size.width * 0.7; //Trying to dynamically change the size and failing. 
    return Container(
      key: _key,
      padding: const EdgeInsets.only(left: 14, right: 14, top: 10, bottom: 10),
      child: Align(
        alignment: (Alignment.topRight),
        child: Container(
          constraints: BoxConstraints(
            maxWidth: maxWidth, // set maximum width to 70% of screen width
          ),
          decoration: BoxDecoration(
            boxShadow: [
              BoxShadow(
                color: Colors.grey.withOpacity(0.2),
                spreadRadius: 1,
                blurRadius: 2,
                offset: const Offset(0, 1),
              ),
            ],
            borderRadius: BorderRadius.circular(20),
            //color: Colors.grey[100],
          ),
          padding: const EdgeInsets.all(12),
          child: Column(
            children: [
              //Add topic if its present
              if (topic != null)
                Row(...
              const SizedBox(
                height: 10,
              ),
              //Messages
              InkWell(
                onLongPress: () {
                  // Provide haptic feedback
                  //HapticFeedback.mediumImpact();
                  showModalBottomSheet(
                    context: context,
                    builder: (context) {
                      return Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: SizedBox(
                          child: Column(
                            mainAxisSize: MainAxisSize.min,
                            children: [
                              ListTile(...
                              ),
                              ListTile(...
                              ),
                              ListTile(
                                trailing: const FaIcon(
                                  FontAwesomeIcons.folderClosed,
                                  size: 16,
                                  color: Colors.blue,
                                ),
                                title: const Text('Topic'),
                                onTap: () async {
                                  //close the bottom modal before navigating
                                  //Navigator.pop(context);

                                  Topic? newTopic =
                                      await _showTopicsDialog(context);

                                  if (newTopic != null && mounted) {
                                    // Check if widget is still in the tree
                                    Note updatedNote = widget.note
                                        .copyWith(topicId: newTopic.id);

                                    // Use a new BuildContext obtained from a Builder widget or a GlobalKey
                                    // instead of the original context that might be deactivated.
                                    final newContext =
                                        GlobalKey().currentContext ?? context;

                                    // Update the topic
                                    Provider.of<NotesProvider>(newContext,
                                            listen: false)
                                        .updateTopic(updatedNote);
                                    // refresh the HomePage if needed
                                  }
                                },
                              ),
                              const ListTile(...,
                              ),
                              ListTile(...
                              ),
                              const SizedBox(
                                height: 20,
                              ),
                            ],
                          ),
                        ),
                      );
                    },
                  );
                },
                child: Text(
                  widget.note.text,
                  style: const TextStyle(fontSize: 15),
                ),
              ),
              const SizedBox(
                height: 8,
              ),
              //Timestamp
              Row(
                mainAxisAlignment: MainAxisAlignment.end,
                children: [...],
              ),
            ],
          ),
        ),
      ),
    );
  }

  //go to edit the note
  void goToNoteEditor(Note note, bool isNewNote) {...

  //delete note
  void deleteNote(Note note) {...

  Future<Topic?> _showTopicsDialog(BuildContext context) async {
    List<Topic> topics = await topicsDb.getAllTopics();
    return showDialog<Topic>(
      context: context,
      builder: (BuildContext context) {
        return SimpleDialog(
          title: const Text('Select Topic'),
          children: topics.map((topic) {
            return SimpleDialogOption(
              onPressed: () {
                Navigator.pop(context, topic);
              },
              child: Text(topic.name),
            );
          }).toList(),
        );
      },
    );
  }
}

我在这里尝试了一些事情。

  1. 删除了 Navigator.pop(已注释掉)- 这部分有效。底部模态不关闭。我仍然有警告 - 我确信这不是正确的做事方式。 “不要跨异步间隙使用“BuildContext”。 尝试重写代码以不引用“BuildContext”。
  2. 我使用全局键并将其传递给 showTopicsDialog 并使用该键作为上下文: context: _key.currentContext!,。一旦我从对话框中选择一个主题,这就会给我一个例外。我假设这是因为我已经弹出了上下文并且我没有原始上下文。我很困惑,因为这不是脚手架。

非常感谢我能在这里得到的任何帮助。也许这段代码一开始有点奇怪。 目标如下:

  1. 用户长按聊天消息。
  2. 底部模式会打开并包含一系列操作。其中一项操作是为消息分配主题/类别。
  3. 选择“主题”应打开一个对话框,其中包含数据库中现有主题的列表。确实如此。 (耶,这里取得了一些成功)
  4. 现在用户选择其中一个主题。这反过来会更新聊天气泡以将类别添加为标题。它还可以编辑消息。
flutter dart asynchronous
1个回答
0
投票

我看到你在这里使用

Stateful widget

因此,当您使用有状态小部件时,您可以通过以下方式摆脱此警告 用这个包装你的代码

if(mounted){
  // Your code where you are using build context.
}

当您将代码包装在这个

if
条件中时,警告将会消失。

mounted
的含义是我们告诉flutter该小部件是否出现在屏幕上。

© www.soinside.com 2019 - 2024. All rights reserved.