You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter调用OpenAI API二次请求UI无更新问题求助

修复Flutter OpenAI应用第二次请求UI不更新的问题

问题根源

  • AnimatedTextKit未设置唯一Key:第二次请求替换chatList后,ListView.builder会复用之前的AnimatedTextKit实例,而该实例的动画已完成(totalRepeatCount:1),不会重新渲染新内容。
  • 聊天列表直接替换而非追加:每次请求直接覆盖chatList,既不符合聊天逻辑,也容易触发Widget复用导致UI不更新。

修复步骤

1. 给AnimatedTextKit添加唯一Key

在ListView的itemBuilder中,为AnimatedTextKit设置基于内容的唯一Key,确保内容更新时Widget会强制重建:

itemBuilder: (context, index) {
  return AnimatedTextKit(
    key: ValueKey(chatList[index].message!.content), // 用消息内容作为唯一标识
    animatedTexts: [
      TypewriterAnimatedText(
          chatList[index].message!.content.toString(),
          speed: Duration(milliseconds: 50))
    ],
    totalRepeatCount: 1,
  );
},

2. 修改聊天列表更新逻辑

将直接替换chatList改为追加新内容,同时清空输入框优化交互:

suffixIcon: IconButton(
    onPressed: () async {
      if (textController.text.trim().isEmpty) return; // 空输入不发送请求
      setState(() {
        isTyping = true;
      });
      
      List<ApiModel> newReply = await apiObj.sentData(textController.text);
      setState(() {
        chatList.addAll(newReply); // 追加新回复到聊天列表
        isTyping = false;
        textController.clear(); // 清空输入框
      });
    },
    icon: Icon(Icons.send)),

3. 可选:添加自动滚动到底部(体验优化)

如果聊天记录较多,可在每次添加新内容后自动滚动到列表底部:

// 先在状态类中定义滚动控制器
ScrollController _scrollController = ScrollController();

// 在ListView中绑定控制器
ListView.builder(
  controller: _scrollController,
  itemCount: chatList.length,
  // ...其他参数
)

// 在更新列表后添加滚动逻辑
setState(() {
  chatList.addAll(newReply);
  isTyping = false;
  textController.clear();
});
// 延迟执行滚动,确保UI已完成更新
WidgetsBinding.instance.addPostFrameCallback((_) {
  _scrollController.animateTo(
    _scrollController.position.maxScrollExtent,
    duration: Duration(milliseconds: 300),
    curve: Curves.easeOut,
  );
});

修改后主代码关键片段

class _MyAppState extends State<MyApp> {
  bool isTyping = false;
  TextEditingController textController = TextEditingController();
  ApiClass apiObj = ApiClass();
  List<ApiModel> chatList = [];
  ScrollController _scrollController = ScrollController(); // 新增滚动控制器

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Chat GPT",
      theme: ThemeData(
          textSelectionTheme:
              TextSelectionThemeData(selectionHandleColor: Colors.transparent)),
      home: Scaffold(
        appBar: PreferredSize(
          preferredSize: Size.fromHeight(50),
          child: AppBar(
            title: Text("AI ChatBot"),
          ),
        ),
        body: Column(
          children: [
            Text(textController.text),
            Expanded(
              child: ListView.builder(
                controller: _scrollController,
                itemCount: chatList.length,
                itemBuilder: (context, index) {
                  return AnimatedTextKit(
                    key: ValueKey(chatList[index].message!.content),
                    animatedTexts: [
                      TypewriterAnimatedText(
                          chatList[index].message!.content.toString(),
                          speed: Duration(milliseconds: 50))
                    ],
                    totalRepeatCount: 1,
                  );
                },
              ),
            ),
            if (isTyping) ...[
              SpinKitThreeBounce(
                size: 18,
                color: Colors.grey,
              )
            ],
            TextField(
              controller: textController,
              decoration: InputDecoration(
                contentPadding: EdgeInsets.symmetric(horizontal: 10),
                hintText: "Type your question here...",
                suffixIcon: IconButton(
                    onPressed: () async {
                      if (textController.text.trim().isEmpty) return;
                      setState(() {
                        isTyping = true;
                      });
                      
                      List<ApiModel> newReply = await apiObj.sentData(textController.text);
                      setState(() {
                        chatList.addAll(newReply);
                        isTyping = false;
                        textController.clear();
                      });
                      WidgetsBinding.instance.addPostFrameCallback((_) {
                        _scrollController.animateTo(
                          _scrollController.position.maxScrollExtent,
                          duration: Duration(milliseconds: 300),
                          curve: Curves.easeOut,
                        );
                      });
                    },
                    icon: Icon(Icons.send)),
                filled: true,
                fillColor: Colors.grey,
                border: InputBorder.none,
              ),
              textAlignVertical: TextAlignVertical.center,
              style: TextStyle(color: Colors.white),
              cursorColor: Colors.amber,
            )
          ],
        ),
      ),
    );
  }
}

内容的提问来源于stack exchange,提问作者Mr. Anonymous

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 07:17:04