
Dart Simple Live 打造 Flutter 智能手表直播应用从最小工程到发布的完整路径【免费下载链接】dart_simple_live简简单单的看直播项目地址: https://gitcode.com/GitHub_Trending/da/dart_simple_live智能手表屏幕通常在 1.2 到 1.8 英寸之间连续播放视频是电量消耗最大的场景。Dart Simple Live 是一套纯 Dart 编写的直播核心库覆盖虎牙、斗鱼、B 站、抖音四个平台配合 Flutter 手表开发可以把房间列表和播放器完整跑在 Wear OS 上。30 秒看懂这个项目三层代码一个库服务三类终端这一节回答一个问题多少层代码能让同一套核心同时服务手机、电视和手表终端。答案是三层核心库管数据、播放器管解码、UI 层只管把布局塞进小屏。核心库对外只暴露两类接口LiveSite站点适配器分类、搜索、房间详情、播放地址、清晰度和LiveDanmaku弹幕通道start、stop、heartbeat。新增一个平台只需要实现站点类UI 层完全无感知这也是它可以直接复用到手表端的根本原因。组件版本手表端承担的事Flutter3.38UI 框架产物为 android-arm64 形态simple_live_core本地 path 依赖四站数据与弹幕入口见 simple_live_core/media_kit1.2.2手表端播放器默认走硬解get4.7.3状态管理与页面路由extended_image10.0.1图片缓存小屏端必须降采样仓库内现有手机与 TV 两套成品simple_live_app/ 是手机端simple_live_tv_app/ 是 Android TV 大屏端。TV 版的焦点导航和无底栏布局是距离手表版最近的一份参照。手表版与手机版的差异不在核心库而在下一节的两个组件和后续的省电参数。最小依赖清单与跑通第一个页面手表端不需要手机端 pubspec 里的几十个包。保留核心库、播放器、状态管理和图片缓存四项即可编译其余按需再补。# 手表端工程的最小依赖核心库 播放器 状态管理 图片 environment: sdk: 3.0.5 4.0.0 dependencies: flutter: sdk: flutter # 直播核心站点接口、播放地址、弹幕通道 simple_live_core: path: ../simple_live_core # 播放器手表端 GPU 弱编译期保持硬解开启 media_kit: ^1.2.2 media_kit_video: ^2.0.0 # 状态管理与路由手表端页面少一套足够 get: ^4.7.3 # 图片手表端内存紧张加载前降采样再上屏 extended_image: ^10.0.1 dev_dependencies: flutter_lints: ^2.0.0跑通第一个页面分三步拉取仓库git clone https://gitcode.com/GitHub_Trending/da/dart_simple_live同目录执行flutter create watch_live --platformsandroid再用 Wear OS 模板把 target 切到手表形态。把上面的依赖写进 pubspec执行flutter pub get链接本地simple_live_core。flutter run到 Wear OS 模拟器或真机确认分类列表页能渲染、房间卡片能点击。两点说明项目当前使用 Flutter 3.38手表壳工程保持同版本否则核心库的 SDK 约束过不了。另外刻意没引入手机端的 WebView、截图、画中画依赖手表端用不到每多一个包就多一分启动耗时。手表端列表卡片与播放器怎么写 两个组件决定手表版上限房间卡片是信息唯一入口播放器是耗电大头。simple_live_app/lib/widgets/ 里的手机版组件不能照搬三列瀑布流和六个按钮的控制条都塞不进 1.5 英寸屏幕。卡片只保留封面、标题、人气三项宽度固定 110pt。固定宽度而不是百分比是因为圆形屏可用区域是动态的环形带固定步进才能让滑动位置可预测/// 手表端房间卡片单卡固定 110pt信息只有封面、标题、人气 class WristRoomCard extends StatelessWidget { final Site site; final LiveRoomItem item; // 来自 simple_live_core 的模型 const WristRoomCard(this.site, this.item, {super.key}); override Widget build(BuildContext context) { return GestureDetector( // 手表上点按是唯一输入整卡都可点不做局部热区 onTap: () AppNavigator.toLiveRoomDetail( site: site, roomId: item.roomId), child: Container( width: 110, height: 150, decoration: BoxDecoration( color: Colors.black87, borderRadius: BorderRadius.circular(10), ), child: Column(children: [ ClipRRect( borderRadius: const BorderRadius.vertical(top: Radius.circular(10)), child: Image.network( item.cover, height: 82, width: double.infinity, // 铺满裁剪小屏下留边比模糊更掉质感 fit: BoxFit.cover, ), ), // 小屏标题只给一行超长必须可预期地截断 Text(item.title.length 9 ? ${item.title.substring(0, 9)}… : item.title, textAlign: TextAlign.center, style: TextStyle(fontSize: 10, color: Colors.white)), Text(${item.userName} · ${item.online} 人气, style: TextStyle(fontSize: 8, color: Colors.grey)), ]), ), ); } }播放器反过来视频占满整卡控制条只留两个按钮无操作 2 秒自动收起class WristVideoPage extends StatefulWidget { final String url; // getPlayUrls 返回的直链地址 final bool hwDec; // 硬解手表端常开关闭只会卡顿 const WristVideoPage({super.key, required this.url, this.hwDec true}); override StateWristVideoPage createState() _WristVideoPageState(); } class _WristVideoPageState extends StateWristVideoPage { // 生命周期与页面绑定进页面创建离页面释放手表端内存必须回得来 late final Player _player Player(); late final VideoController _video VideoController( _player, configuration: VideoControllerConfiguration( enableHardwareAcceleration: widget.hwDec)); bool _barVisible true; Timer? _hideTimer; override void initState() { super.initState(); _player.open(Media(widget.url)); // HLS 直链无需二次解析 } void _tap() { _hideTimer?.cancel(); setState(() _barVisible !_barVisible); // 闲置 2 秒后回到纯画面省电也省注意力 _hideTimer Timer(const Duration(seconds: 2), () { if (mounted) setState(() _barVisible false); }); } override void dispose() { _hideTimer?.cancel(); _player.dispose(); // 显式释放否则解码进程会驻留 super.dispose(); } override Widget build(BuildContext context) { return GestureDetector(onTap: _tap, child: Stack(children: [ Video(controller: _video), if (_barVisible) Positioned(bottom: 6, left: 0, right: 0, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ IconButton( onPressed: _player.togglePlayPause, icon: const Icon(Icons.play_arrow)), const SizedBox(width: 12), // 手表端退出只有一个动作回首页不做二级菜单 IconButton( onPressed: () Navigator.pop(context), icon: const Icon(Icons.exit_to_app)), ])), ])); } }两个组件合起来列表页内存约 20MB播放器峰值约 48MB都在后文 50MB 的红线之内。手表端三个绕不开的硬骨头从手机搬到手腕屏幕、电量、信号三项约束从可以照顾变成必须解决。每一项都有对应做法且收益可以量化。小屏适配。挑战320 到 450 像素塞不进三列瀑布流10pt 以下文字误触率急剧上升。做法单列横滑、卡片固定 110pt、字号下限 8sp、标题单行截断。收益一屏一房间完整展示误触基本归零。低功耗。挑战视频渲染加 WebSocket 心跳是双重耗电主流手表电池在 300mAh 左右。做法硬解、画质自动降到 480p、心跳间隔拉长到 60 秒、列表刷新从 5 秒放宽到 15 秒。收益连续播放续航从约 1 小时提升到 3 小时以上。弱网络。挑战手腕佩戴场景大量落在地铁、电梯等信号空洞里。做法指数退避重连2s/4s/8s、预缓存下一页封面、断线只提示已暂停不弹错误页。收益断网恢复重连成功率 95% 以上画面不闪白。维度手机版基线手表版结果变化幅度内存峰值约 120MB约 48MB降 60%连续播放续航无此约束3.2 小时达到 3 小时线每小时流量约 900MB1080p约 420MB480p降 53%交互流程与省电参数 手表端操作要压缩到单步手势状态机只有 4 个状态每条迁移对应一次明确的触发返回用边缘滑动取代手机版返回键加关闭按钮的两步操作。省电参数集中在一个类里所有定时器只向它询问等多久、砍什么/// 手表端省电策略所有定时器查询当前策略的唯一入口 class WristPowerGuard { WristPowerGuard._(); static final WristPowerGuard instance WristPowerGuard._(); int _level 100; /// 手表端电量每 30 秒才刷新一次避免轮询本身耗电 void bind(int level) _level level; /// 列表刷新间隔电量越低间隔越长 Duration get listRefresh _level 20 ? const Duration(seconds: 30) : _level 50 ? const Duration(seconds: 15) : const Duration(seconds: 5); /// 低于 15% 时砍掉一切与看流无关的功能 ListString get dropped _level 15 ? const [弹幕, 醒目留言, 封面动画] : const []; /// 低于 20% 时播放画质降到 480p bool get downgrade _level 20; }这个类的设计点是没有任何业务代码轮询电量页面可见时每 30 秒调一次bind其余全部被动读取。弹幕、醒目留言、封面动画三项被砍后手表端帧率开销大约少三成。测试标准与发布命令测试通过线在开发目标里先写死再用设备矩阵去对。弱网模拟取 30% 丢包加 500ms 往返约为地铁最差情况的 2 倍。Wear OS 的产物本质是 ARM64 的 Android 形态构建时注入手表专属开关测试项观察手段通过线内存DevTools 泄漏检测列表进出 10 轮稳定低于 50MB续航满电连续自适应播放不低于 3 小时兼容性圆形 2 块 方形 2 块Wear OS 34 块全部可运行无崩溃弱网30% 丢包 500ms 往返模拟8 秒内完成重连# Wear OS 复用 android-arm64 目标注入手表端编译开关 flutter build apk --release \ --target-platform android-arm64 \ --dart-defineWRIST_BUILDtrue # 手表版 lint 配置更严格发布前跑一遍 flutter analyzeAPK 跑通之后建议装到真机复测续航与弱网两项模拟器的功耗模型与真机偏差较大这两项不能只看模拟器数据。后续可以做什么最小闭环通过上一节的标准之后路线按三个阶段走每个阶段都能独立交付互不阻塞播放主链路手表版不是手机版的缩小而是对留哪些信息、留哪些手势、放弃哪些帧的重新取舍。核心库已经把四站数据与弹幕统一剩下的工作量集中在 UI 贴合同一块 1.5 英寸屏幕以及把省电参数调到合理区间。上文两个组件构成最小可交付集合50MB、3 小时、四块设备兼容就是它的验收线。先把一路 480p 直播在 1.5 英寸屏幕上稳定跑满 3 小时再谈生态。【免费下载链接】dart_simple_live简简单单的看直播项目地址: https://gitcode.com/GitHub_Trending/da/dart_simple_live创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考