2025年实战Flutter3仿DeepSeek/豆包 Stream流式打字输出AI聊天对话,正式完结啦。
flutter3-deepseek-chat:2025跨平台ai新作Flutter3.27+DeepSeek+Getx+Dio+Markdown搭建流式输出ai对话项目。Flutter3 集成 Deepseek-V3 API 会话大模型。支持手机端/桌面端、代码块高亮、对话本地存储等功能。
运用技术
- 编辑器:vscode
- 技术框架:flutter3.27.1+dart3.6.0
- ai大模型:deepseek-v3
- 网络请求:dio^5.8.0+1
- 路由/状态管理:get^4.7.2
- 本地存储:get_storage^2.1.1
- markdown解析:flutter_markdown^0.7.7
- 高亮插件:flutter_highlight^0.7.0
项目框架结构
使用最新版跨平台框架Flutter3.27搭建项目模板,集成DeepSeek聊天大模型。
flutter3配置环境变量.env
在flutter中配置环境变量,使用了flutter_dotenv插件。
// 安装插件
flutter pub add flutter_dotenv
在项目根目录下新建一个.env配置文件。
# 项目名称
APP_NAME = 'Flutter3-DeepSeek'
# DeepSeek API配置
DEEPSEEK_API_KEY = your apikey
DEEPSEEK_BASE_URL = https://api.deepseek.com
去deepseek官网申请一个api key并替换掉.env文件里的key即可畅快体验流式对话了。
项目入口配置main.dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:shirne_dialog/shirne_dialog.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'controller/app.dart';
import 'controller/chat.dart';
// 引入路由配置
import 'router/index.dart';
void main() async {
// 初始化存储服务
await GetStorage.init();
// 将.env文件内容加载到dotenv中
await dotenv.load(fileName: '.env');
// 注册GetxController
Get.put(AppStore());
Get.put(ChatStore());
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
// 获取AppStore实例
final appStore = AppStore.to;
return GetMaterialApp(
title: 'Flutter3 DeepSeek',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Color(0xFF4F6BFE)),
useMaterial3: true,
fontFamily: Platform.isWindows ? 'Microsoft YaHei' : null,
),
// 初始路由
initialRoute: appStore.isLogin ? '/' : '/login',
// 路由页面
getPages: routePages,
navigatorKey: MyDialog.navigatorKey,
localizationsDelegates: [
ShirneDialogLocalizations.delegate,
],
);
}
}
项目布局模板
flutter-deepseek整体分为顶部导航条+对话区域+底部编辑区三个模块。
@override
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
backgroundColor: Colors.white,
appBar: AppBar(
...
actions: [
IconButton(icon: Icon(Icons.try_sms_star_outlined), onPressed: () => handleCreate(),),
],
),
body: Center(
child: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: 750.0,
),
child: Flex(
direction: Axis.vertical,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Stack(
children: [
GestureDetector(
child: ScrollConfiguration(
behavior: CustomScrollBehavior().copyWith(scrollbars: false),
// GetBuilder响应流式输出
child: Obx(() {
if (chatStore.currentMessages.isEmpty) {
// 欢迎信息
return Welcome(
onChanged: (value) {
textEditingController.text = value;
},
);
}
return ListView.builder(
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag, // 当滚动时候隐藏键盘
controller: scrollController,
padding: EdgeInsets.all(10.0),
reverse: true,
shrinkWrap: true,
itemCount: chatStore.currentMessages.length,
itemBuilder: (context, index) {
...
}
);
}),
),
onTap: () {
focusNode.unfocus();
},
),
// 滚动到底部
AnimatedPositioned(
...
),
],
),
),
// 底部编辑器区域
ChatEditor(controller: textEditingController),
]
),
),
),
// 侧边栏
drawer: Drawer(
child: Sidebar(),
),
);
}
flutter3+get路由配置
在flutter中通过get来管理配置页面路由。
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controller/app.dart';
/* 引入路由页面 */
import '../pages/auth/login.dart';
import '../pages/auth/register.dart';
import '../pages/index/index.dart';
import '../pages/aihub/index.dart';
import '../pages/setting/index.dart';
// 路由地址集合
final Map<String, Widget> routes = {
'/': Home(),
'/aihub': Aihub(),
'/setting': Setting(),
};
final List<GetPage> routeList = routes.entries.map((e) => GetPage(
name: e.key, // 路由名称
page: () => e.value, // 路由页面
transition: Transition.rightToLeftWithFade, // 跳转路由动画
middlewares: [RouteMiddleware()], // 路由中间件
)).toList();
final List<GetPage> routePages = [
GetPage(name: '/login', page: () => const Login()),
GetPage(name: '/register', page: () => const Register()),
...routeList,
];
// 路由中间件拦截验证
class RouteMiddleware extends GetMiddleware {
final appStore = AppStore.to;
@override
RouteSettings? redirect(String? route) {
return appStore.isLogin ? null : const RouteSettings(name: '/login');
}
}
另外支持运行到windows桌面端,以750px宽度显示布局结构。
flutter3封装markdown解析
在flutter3中解析流返回的markdown结构,使用到 flutter_markdown 组件来解析markdown语法结构。使用 flutter_highlight 组件来高亮代码块。
特点
- 支持代码块横向滚动、代码块、行内代码高亮
- 支持代码块复制功能
- 支持表格渲染功能
- 支持网络图片宽度100%渲染及预览
- 支持网络链接跳转功能
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:flutter_highlight/flutter_highlight.dart';
import 'package:flutter_highlight/themes/github.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:easy_image_viewer/easy_image_viewer.dart';
import 'package:markdown/markdown.dart' as md;
class FMarkdown extends StatefulWidget {
const FMarkdown({
super.key,
required this.data,
});
final String data;
@override
State<FMarkdown> createState() => _FMarkdownState();
}
class _FMarkdownState extends State<FMarkdown> {
@override
Widget build(BuildContext context) {
return MarkdownBody(
data: widget.data,
fitContent: false,
styleSheet: MarkdownStyleSheet(
blockSpacing: 12.0,
// 表格
tableBorder: TableBorder.all(color: Colors.black12),
// 水平线
horizontalRuleDecoration: BoxDecoration(
border: Border(top: BorderSide(color: Colors.black12, width: 1.0)),
),
// 代码块
codeblockDecoration: BoxDecoration(
color: Color(0xfff8f8f8),
borderRadius: BorderRadius.circular(10.0),
),
// 引用
blockquotePadding: EdgeInsets.only(left: 16.0, top: 8.0, bottom: 8.0),
blockquoteDecoration: BoxDecoration(
border: Border(left: BorderSide(color: Colors.black12, width: 4.0)),
)
),
builders: {
// 自定义代码/代码块构建
'code': CustomCodeBuilder(),
},
// 自定义图片构建
sizedImageBuilder: (config) => ImageBuilderWidget(config: config),
// 点击链接
onTapLink: (text, href, title) async {
if (href != null) {
if(await canLaunchUrl(Uri.parse(href))) {
await launchUrl(Uri.parse(href));
}else {
debugPrint('无法访问 $href');
}
}
},
);
}
}
flutter3对接deepseek api
flutter3中通过dio来请求deepseek api实战流输出。
final response = await dio.post(
'$baseURL/v1/chat/completions',
options: Options(
// 响应超时
receiveTimeout: const Duration(seconds: 60),
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer $apiKEY",
},
// 设置响应类型为流式响应
responseType: ResponseType.stream,
),
data: {
// 多轮会话
'messages': widget.multiConversation ? chatStore.historySession : [{'role': 'user', 'content': editorValue}],
'model': 'deepseek-chat', // deepseek-chat对话模型 deepseek-reasoner推理模型
'stream': true, // 流式输出
'max_tokens': 8192, // 限制一次请求中模型生成 completion 的最大 token 数(默认使用 4096)
'temperature': 0.4, // 严谨采样 越低越严谨(默认1)
}
);
OK,以上就是flutter3+deepseek搭建流输出ai项目的一些分享。感谢大家的阅读与支持!
基于uniapp+vue3+deepseek+markdown搭建app版流式输出AI模板
DeepSeek+Electron35+Vite6+Markdown桌面端AI流式聊天模板
vue3.5+deepseek+arco+markdown搭建web网页版流式输出AI模板
vue3.5+deepseek搭建mobile版流式打字ai模板
自研tauri2.0+vite6.x+vue3+rust+arco-design桌面版os管理系统Tauri2-ViteOS
自研tauri2.0+vite5+vue3+element-plus电脑版exe聊天系统Vue3-Tauri2Chat
原创electron31+vite5.x+elementPlus桌面端后台管理系统
uni-vue3-wechat:基于uni-app+vue3+pinia2多端仿微信App聊天