简介:本文详细解析如何使用Flutter3构建仿Deepseek/ChatGPT的流式聊天界面,并完成与deepseek-chat API的对接,涵盖界面设计、流式响应处理、状态管理及错误处理等核心环节。
分层架构设计
采用MVC模式分离业务逻辑与UI渲染:
核心功能模块
消息气泡组件
class MessageBubble extends StatelessWidget {final String text;final bool isUser;const MessageBubble({super.key,required this.text,required this.isUser,});@overrideWidget build(BuildContext context) {return Align(alignment: isUser ? Alignment.centerRight : Alignment.centerLeft,child: Container(margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),padding: const EdgeInsets.all(12),decoration: BoxDecoration(color: isUser ? Colors.blue : Colors.grey[200],borderRadius: BorderRadius.circular(16),),child: Text(text),),);}}
流式消息渲染
使用StreamBuilder监听API响应流:
StreamBuilder<List<String>>(stream: _chatController.messageStream,builder: (context, snapshot) {if (snapshot.hasError) {return ErrorWidget(snapshot.error!);}final messages = snapshot.data ?? [];return ListView.builder(reverse: true,itemCount: messages.length,itemBuilder: (context, index) => MessageBubble(text: messages[index],isUser: index % 2 == 0, // 简单区分用户与AI消息),);},)
输入框与发送逻辑
TextField(controller: _inputController,onSubmitted: (text) async {if (text.trim().isEmpty) return;_addMessage(text, isUser: true);final response = await _chatController.sendMessage(text);_addMessage(response, isUser: false);_inputController.clear();},decoration: const InputDecoration(hintText: '输入消息...',suffixIcon: IconButton(icon: Icon(Icons.send),onPressed: null, // 实际通过onSubmitted触发),),)
API请求封装
class ChatApiClient {final String _baseUrl = 'https://api.deepseek-chat.com/v1';final Dio _dio = Dio();Future<String> sendMessage(String prompt) async {final response = await _dio.post('$_baseUrl/chat/completions',data: {'model': 'deepseek-chat','prompt': prompt,'stream': true, // 启用流式响应},options: Options(headers: {'Authorization': 'Bearer YOUR_API_KEY'}),);return _processStreamResponse(response);}String _processStreamResponse(Response response) {// 实际需解析SSE流数据,示例简化处理return response.data['choices'][0]['text'];}}
流式响应处理
使用http包解析Server-Sent Events(SSE):
Stream<String> getMessageStream(String prompt) async* {final client = http.Client();final request = http.Request('POST',Uri.parse('https://api.deepseek-chat.com/v1/chat/completions'),);request.headers['Authorization'] = 'Bearer YOUR_API_KEY';request.body = jsonEncode({'model': 'deepseek-chat','prompt': prompt,'stream': true,});final streamedResponse = await client.send(request);await for (final response in streamedResponse.stream.transform(utf8.decoder)) {final lines = response.split('\n');for (final line in lines) {if (line.startsWith('data: ')) {final data = jsonDecode(line.substring(6))['choices'][0]['delta']['content'];if (data != null) yield data;}}}}
Bloc模式实现
part 'chat_bloc.freezed.dart';@freezedclass ChatState with _$ChatState {const factory ChatState.initial() = _Initial;const factory ChatState.loading() = _Loading;const factory ChatState.loaded(List<String> messages) = _Loaded;const factory ChatState.error(String message) = _Error;}class ChatBloc extends Bloc<ChatEvent, ChatState> {final ChatApiClient _apiClient;ChatBloc(this._apiClient) : super(ChatState.initial()) {on<SendMessage>((event, emit) async {emit(ChatState.loading());try {final stream = _apiClient.getMessageStream(event.prompt);await for (final chunk in stream) {// 实时更新状态(需配合StreamController)}// 实际需实现完整流处理逻辑} catch (e) {emit(ChatState.error(e.toString()));}});}}
性能优化策略
hive或sqflite存储历史记录 常见问题解决方案
_dio.httpClientAdapter = DefaultHttpClientAdapter()..onHttpClientCreate = (client) {client.badCertificateCallback = (cert, host, port) => false; // 仅调试用client.connectionTimeout = const Duration(seconds: 10);};
Future<void> _retryRequest(Function request) async {int retryCount = 0;const maxRetries = 3;while (retryCount < maxRetries) {try {await request();break;} catch (e) {retryCount++;await Future.delayed(Duration(seconds: 2 ^ retryCount));}}}
日志与监控
logger包记录关键操作 多平台适配
功能扩展建议
flutter_tts与speech_to_text intl包实现国际化
lib/├── api/│ └── chat_api_client.dart├── bloc/│ └── chat_bloc.dart├── components/│ ├── message_bubble.dart│ └── loading_indicator.dart├── models/│ └── message.dart├── pages/│ └── chat_page.dart└── main.dart
通过以上实现,开发者可快速构建一个具备流式响应能力的AI聊天界面,并灵活对接deepseek-chat等后端服务。实际开发中需根据具体API文档调整请求参数与响应解析逻辑,同时建议通过单元测试与集成测试确保功能稳定性。