升级执行与状态展示
本页介绍 JL_OTA Flutter 示例应用中固件升级(OTA)的执行流程与状态展示机制,涵盖升级页面(UpdatePage)、升级进度/结果对话框(OtaDialog)、全局连接状态管理(ConnectionStateManager)以及与原生插件、平台通道(MethodChannel)的交互方式。
Purpose and Scope
本页聚焦于示例应用(code/JL_OTA/example)中「升级执行与状态展示」这条完整能力链路:
- 升级入口:
UpdatePage的初始化、状态装配与 UI 呈现; - 升级执行:通过
OtaConnectionManager、平台通道与jl_ota插件交互,触发固件升级; - 状态展示:
OtaDialog对升级进度、成功/失败结果的实时渲染,以及DataNotifier/ConnectionStateManager对状态的全局分发; - 辅助设施:
OtaFileManager文件列表管理、DialogManager对话框装配、PopupMenuManager菜单管理。
以下相关主题属于兄弟页面,不在本页展开:设备扫描/连接(设备页 devices_page)、固件文件下载与分享(file_share_page、download_file_dialog)、设置项(setting_page)等。本页只描述「升级执行与状态展示」本身。
Overview
UpdatePage 是示例应用的核心功能模块之一,其职责在源码注释中有明确界定(update_page.dart):
- 显示当前设备的连接状态与设备类型;
- 提供文件选择入口(本地添加、电脑传输、扫码下载);
- 管理 OTA 文件列表(查看、选择、删除);
- 执行固件升级操作;
- 与原生平台交互完成文件与通道操作。
整个机制的核心思路是 事件驱动 + 全局状态分发:jl_ota 插件通过 BLE 事件流(BleEventStream)上报设备连接与 OTA 状态,示例应用将这些事件写入 DataNotifier(Provider 全局状态),UpdatePage 与 OtaDialog 各自订阅并渲染。这样升级过程中的每个阶段(查文件 → 传输 → 校验 → 成功/失败)都能实时反映在 UI 上,且页面与弹窗解耦。
Architecture
flowchart TD
subgraph sg_UI["UI Layer (example)"]
UpdatePage["UpdatePage (升级页)"]
OtaDialog["OtaDialog (升级状态弹窗)"]
ConnectionStateManager["ConnectionStateManager<br/>单例 ChangeNotifier"]
end
subgraph sg_Managers["Manager Layer (example)"]
OtaFileManager["OtaFileManager"]
DialogManager["DialogManager"]
PopupMenuManager["PopupMenuManager"]
OtaConnectionManager["OtaConnectionManager"]
end
subgraph sg_Plugin["jl_ota 插件层"]
BleEventStream["BleEventStream"]
BleMethod["BleMethod"]
MethodChannel["MethodChannel<br/>com.jieli.ble_plugin/methods"]
end
subgraph sg_Native["原生平台"]
Native["Android/iOS BLE 与 OTA 实现"]
end
subgraph sg_State["全局状态"]
DataNotifier["DataNotifier (Provider)"]
end
UpdatePage --> OtaFileManager
UpdatePage --> DialogManager
UpdatePage --> PopupMenuManager
UpdatePage --> OtaConnectionManager
UpdatePage -->|"otaData"| DataNotifier
DataNotifier -->|"状态事件"| UpdatePage
DataNotifier -->|"状态事件"| OtaDialog
OtaDialog -->|"订阅 OTA 状态流"| BleEventStream
OtaConnectionManager --> BleMethod
UpdatePage -->|"setMethodCallHandler"| MethodChannel
BleMethod --> MethodChannel
MethodChannel --> Native
Native -->|"BLE/OTA 事件"| BleEventStream
ConnectionStateManager -->|"connectState"| UpdatePage
各组件职责说明:
UpdatePage:升级功能的入口页面(StatefulWidget),负责装配各管理器、读取全局otaData渲染设备状态、提供文件添加入口与升级操作入口;OtaDialog:升级过程中的底部弹窗,展示进度条、当前阶段消息与成功/失败结果,并根据 OTA 状态决定是否允许用户关闭;OtaConnectionManager:连接管理封装,通过BleMethod与插件交互,并在 OTA 数据被清理时回调_cleanOtaData;OtaFileManager:管理 OTA 文件列表与选中文件,通过回调驱动页面setState;DialogManager:统一构建各类对话框(OTA 弹窗、下载弹窗、权限确认等);DataNotifier:Provider 全局状态,承载otaData(含KEY_STATE、KEY_DEVICE_TYPE等键),是升级状态展示的数据中枢;ConnectionStateManager:单例ChangeNotifier,维护设备连接状态并通知监听者;BleEventStream/BleMethod:jl_ota插件暴露给 Dart 层的事件流与方法调用接口;MethodChannel:名为com.jieli.ble_plugin/methods的平台通道,UpdatePage通过它接收原生侧回调。
升级页面的状态模型与 UI 呈现
页面状态字段
_UpdatePageState 维护了升级页的全部运行状态(update_page.dart):
class _UpdatePageState extends State<UpdatePage> {
late int _state = AppConstants.connectionDisconnect;
late String _deviceType = '';
List<Map<String, String>> _otaFileList = []; // 用于存储文件列表
String? _selectedFilePath; // 用于存储当前选中的文件路径
final GlobalKey _addFileButtonKey = GlobalKey();
Map<String, dynamic>? _otaData;
bool _isStorageEnvironmentChecked = false;
bool _isOtaStarted = false;
bool _isInitialDataLoaded = false;
static const MethodChannel _methodChannel = MethodChannel(
'com.jieli.ble_plugin/methods',
);
StreamSubscription<List<Map<String, String>>>? _otaFileListSubscription;
...
}
关键字段的设计意图:
_state保存设备连接状态,默认AppConstants.connectionDisconnect(未连接),在build阶段从otaData[BleEventConstants.KEY_STATE]同步;_deviceType保存设备类型字符串,来自otaData[BleEventConstants.KEY_DEVICE_TYPE];当连接断开时主动清空,避免展示过期的设备类型;_otaFileList与_selectedFilePath分别对应 OTA 文件列表与当前选中文件,供升级时使用;_isOtaStarted用于区分「用户主动开始升级」与「页面重建读取历史状态」:只有未开始升级时,才用otaData回填连接状态,防止升级进行中被旧数据覆盖。
状态同步的构建期逻辑
状态同步发生在 build 方法内(update_page.dart):
Widget build(BuildContext context) {
final loc = AppLocalizations.of(context)!;
_otaData = Provider.of<DataNotifier>(context).otaData;
final isAndroid = AppUtil.isAndroid;
if (!_isOtaStarted && _otaData != null && _otaData!.isNotEmpty) {
_state = _otaData?[BleEventConstants.KEY_STATE] ?? 0;
_deviceType = _otaData?[BleEventConstants.KEY_DEVICE_TYPE] ?? '';
if (_state == AppConstants.connectionDisconnect) {
_deviceType = '';
}
}
...
}
这里采用「读取 Provider 全局状态 → 回填本地字段」的模式:DataNotifier 是全局唯一的 OTA 数据源(通过 Provider.of 获取),页面每次重建都会拿到最新事件数据。之所以限定 !_isOtaStarted,是为了保证升级一旦开始,页面不再用历史事件覆盖运行中的升级状态,而是由 OtaDialog 独立订阅事件流来展示进度。
设备状态栏渲染
页面顶部展示「设备状态:已连接/未连接」与「设备类型」,样式用 HexColor 与 loc(国际化文案)驱动(update_page.dart):
Text.rich(
TextSpan(
children: [
TextSpan(
text: '${loc.deviceStatus}:',
style: TextStyle(
fontSize: 15,
color: HexColor.hexColor("#242424"),
fontWeight: FontWeight.bold,
),
),
TextSpan(
text: _state == AppConstants.connectionOK
? loc.connected
: loc.disconnected,
style: TextStyle(
fontSize: 15,
color: HexColor.hexColor("#628DFF"),
fontWeight: FontWeight.bold,
),
),
],
),
),
SizedBox(height: 10),
Text(
'${loc.deviceType}:$_deviceType',
...
),
设计意图:状态与设备类型直接取自 jl_ota 插件的事件常量(BleEventConstants.KEY_STATE / KEY_DEVICE_TYPE),保证 UI 与底层 BLE 状态始终一致;文案走 AppLocalizations 国际化,便于多语言发布。
管理器装配与平台通道
初始化流程
initState 中依次完成:装配管理器 → 初始化 → 注册平台通道回调 → 恢复上次选择的 OTA 文件路径(update_page.dart):
void initState() {
super.initState();
_initializeManagers();
_initialize();
_methodChannel.setMethodCallHandler(_handleMethodCall);
FilePreferenceManager.loadOtaPath().then((path) {
setState(() {
_selectedFilePath = path;
});
});
}
_initializeManagers()创建OtaFileManager、DialogManager、PopupMenuManager、OtaConnectionManager四个管理器;_methodChannel.setMethodCallHandler(_handleMethodCall)让 Dart 侧可以接收原生平台主动发来的方法调用(例如文件扫描结果、设备回调);FilePreferenceManager.loadOtaPath()异步恢复上次选中的文件路径,提升用户体验(断点续选)。
管理器装配细节
void _initializeManagers() {
_otaFileManager = OtaFileManager(
otaFileList: _otaFileList,
onFileListUpdated: (newList) {
setState(() {
_otaFileList = newList;
});
},
onSelectedFileChanged: (filePath) {
setState(() {
if (_selectedFilePath == filePath) {
_selectedFilePath = null;
}
});
},
);
_dialogManager = DialogManager(
context: context,
methodChannel: _methodChannel,
);
_popupMenuManager = PopupMenuManager();
_otaConnectionManager = OtaConnectionManager(
onOtaDataCleaned: _cleanOtaData,
);
}
装配方式体现了解耦思想:
- 回调式文件管理:
OtaFileManager不持有BuildContext,通过onFileListUpdated/onSelectedFileChanged回调让页面自行setState,管理器可独立测试; DialogManager持有 context 与方法通道:对话框经常需要调用原生能力(如文件保存、扫码),因此把methodChannel注入其中;OtaConnectionManager反向回调:当原生侧清理 OTA 数据时,通过onOtaDataCleaned: _cleanOtaData通知页面重置状态。
升级状态对话框(OtaDialog)
状态与进度模型
OtaDialog 是升级执行期间的状态展示载体,其内部状态包括进度、OTA 阶段、当前消息与成功标志(ota_dialog.dart):
class _OtaDialogState extends State<OtaDialog> {
int _progress = 0;
String _otaState = BleEventConstants.KEY_STATE_START;
final String _failureReason = '';
String _otaType = BleEventConstants.KEY_CHECK_FILE;
String _currentMessage = '';
bool _isSuccess = false;
StreamSubscription? _otaStateSubscription;
bool _isLoadingDialogShowing = false;
void initState() {
super.initState();
_startListeningToOtaState();
}
}
_otaState初始为KEY_STATE_START(升级开始),_otaType初始为KEY_CHECK_FILE(查文件阶段);_startListeningToOtaState()在initState中订阅BleEventStream的 OTA 状态事件,弹窗因此能在不依赖页面setState的情况下实时更新;- 成功/失败结果分别通过
_isSuccess与内置的ic_success_big.png/ic_fail_big.png图标呈现。
关闭控制(PopScope)
弹窗是否允许被关闭,取决于当前 OTA 状态(ota_dialog.dart):
// 根据状态决定是否允许关闭(成功或失败状态可以关闭)
final bool canPop =
_otaState == BleEventConstants.KEY_STATE_IDLE ||
_otaState == BleEventConstants.ERROR;
return PopScope(
canPop: canPop,
onPopInvokedWithResult: (bool didPop, Object? result) {
if (!canPop) {
return;
}
},
...
);
设计意图:升级过程是不可中断的关键操作。只有当 OTA 进入 KEY_STATE_IDLE(空闲/完成)或 ERROR(出错)终态时,才允许用户关闭弹窗;升级进行中按返回键会被 PopScope 拦截,避免误触导致升级中断。
视觉与布局常量
弹窗样式全部抽离到 _OtaDialogConstants 常量类(ota_dialog.dart),包括边距、圆角、进度条高度(3px)、字号、主题色(进度蓝 0xFF398BFF、文字主色 0xFF242424)等。抽常量的好处是保证各阶段(升级中/重连中/完成态)视觉一致,且后续主题调整只改一处。
全局连接状态管理(ConnectionStateManager)
ConnectionStateManager 是全局唯一的连接状态单例,基于 ChangeNotifier 实现(connection_state_manager.dart):
class ConnectionStateManager extends ChangeNotifier {
static ConnectionStateManager? _instance;
ConnectionStateManager._internal();
factory ConnectionStateManager() {
_instance ??= ConnectionStateManager._internal();
return _instance!;
}
int _connectState = AppConstants.connectionFailed;
int get connectState => _connectState;
void updateConnectState(int newState) {
if (_connectState != newState) {
_connectState = newState;
notifyListeners();
}
}
static int get currentState => _instance?._connectState ?? AppConstants.connectionFailed;
}
要点:
- 私有构造函数 + 工厂单例,保证全应用只有一份连接状态,避免多页面状态不同步;
updateConnectState只在状态变化时notifyListeners(),避免无意义的重建通知;static currentState提供静态读取入口,便于非 Widget 场景(如管理器)快速获取当前状态;- 默认值
AppConstants.connectionFailed,与UpdatePage默认的connectionDisconnect互补,覆盖「尚未连接」与「连接失败」两种初始场景。
Core Flow:升级执行与状态回传的完整链路
从用户选择固件文件、触发升级,到状态实时展示、最终成功/失败落地的全过程如下:
sequenceDiagram
participant U as 用户
participant P as UpdatePage
participant FM as OtaFileManager
participant OC as OtaConnectionManager
participant PL as jl_ota 插件 (BleMethod)
participant N as 原生 BLE/OTA
participant ES as BleEventStream
participant DN as DataNotifier
participant OD as OtaDialog
U->>P: 添加/选择固件文件
P->>FM: 更新文件列表与选中路径
U->>P: 点击「升级」按钮
P->>OC: 发起 OTA 升级指令
OC->>PL: 调用升级方法
PL->>N: 平台通道下发指令
N-->>ES: 上报 OTA 状态事件 (查文件/传输/校验)
ES-->>DN: 写入全局 otaData
DN-->>P: 页面读取 otaData (仅未开始时回填)
DN-->>OD: 弹窗订阅状态流
OD-->>U: 渲染进度条与阶段消息
N-->>ES: 上报成功/失败终态
ES-->>OD: KEY_STATE_IDLE / ERROR
OD-->>U: 展示成功/失败结果,允许关闭
各步骤说明:
- 文件准备:用户在
UpdatePage通过「本地添加 / 电脑传输 / 扫码下载」三个入口之一获得固件文件,OtaFileManager维护列表与选中项; - 触发升级:点击升级按钮后,
OtaConnectionManager通过BleMethod(jl_ota插件的方法封装)向原生层下发升级指令; - 原生执行与事件上报:原生 BLE/OTA 实现执行查文件(
KEY_CHECK_FILE)、传输、校验等阶段,并通过BleEventStream持续上报事件; - 全局状态分发:事件写入
DataNotifier.otaData;UpdatePage在未开始升级时据此回填连接状态与设备类型,OtaDialog则直接订阅事件流渲染进度; - 终态收敛:升级进入
KEY_STATE_IDLE(成功)或ERROR(失败)后,弹窗展示结果图标与文案,PopScope.canPop变为true,用户可关闭弹窗。
Usage Examples
示例一:初始化平台通道回调并恢复上次文件路径
UpdatePage.initState 中注册 MethodChannel('com.jieli.ble_plugin/methods') 的方法处理器,并异步恢复上次选中的 OTA 文件:
void initState() {
super.initState();
_initializeManagers();
_initialize();
_methodChannel.setMethodCallHandler(_handleMethodCall);
FilePreferenceManager.loadOtaPath().then((path) {
setState(() {
_selectedFilePath = path;
});
});
}
示例二:根据 OTA 状态控制弹窗可关闭性
OtaDialog 用 PopScope 将「能否关闭」与「OTA 状态」绑定,只有终态(空闲或出错)才允许关闭:
// 根据状态决定是否允许关闭(成功或失败状态可以关闭)
final bool canPop =
_otaState == BleEventConstants.KEY_STATE_IDLE ||
_otaState == BleEventConstants.ERROR;
return PopScope(
canPop: canPop,
onPopInvokedWithResult: (bool didPop, Object? result) {
if (!canPop) {
return;
}
},
...
);
示例三:单例连接状态更新与通知
ConnectionStateManager 提供全局唯一的连接状态,并在状态变化时通知所有监听者:
int _connectState = AppConstants.connectionFailed;
int get connectState => _connectState;
void updateConnectState(int newState) {
if (_connectState != newState) {
_connectState = newState;
notifyListeners();
}
}
static int get currentState => _instance?._connectState ?? AppConstants.connectionFailed;
来源:connection_state_manager.dart
Configuration Options
升级执行与状态展示相关的可配置项分为三类:平台通道、事件常量、UI 常量。
平台通道
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| 方法通道名称 | const String | com.jieli.ble_plugin/methods | UpdatePage 与原生平台通信的 MethodChannel 名称,用于接收原生回调(见 update_page.dart) |
状态常量(来自 jl_ota 插件包)
| 常量 | 用途 | 出处 |
|---|---|---|
BleEventConstants.KEY_STATE | 从 otaData 中读取连接/OTA 状态 | update_page.dart |
BleEventConstants.KEY_DEVICE_TYPE | 从 otaData 中读取设备类型 | update_page.dart |
BleEventConstants.KEY_STATE_START | OTA 状态初始值(开始) | ota_dialog.dart |
BleEventConstants.KEY_CHECK_FILE | OTA 类型初始值(查文件) | ota_dialog.dart |
BleEventConstants.KEY_STATE_IDLE | 升级完成(空闲)终态,允许关闭弹窗 | ota_dialog.dart |
BleEventConstants.ERROR | 升级出错终态,允许关闭弹窗 | ota_dialog.dart |
AppConstants.connectionOK | 设备已连接,展示「已连接」 | update_page.dart |
AppConstants.connectionDisconnect | 设备未连接,展示「未连接」并清空设备类型 | update_page.dart |
AppConstants.connectionFailed | ConnectionStateManager 的默认连接状态 | connection_state_manager.dart |
OtaDialog UI 常量(_OtaDialogConstants)
| 常量 | 类型 | 默认值 | 说明 |
|---|---|---|---|
dialogHorizontalMargin | double | 12.0 | 弹窗水平外边距 |
dialogBottomMargin | double | 34.0 | 弹窗底部外边距 |
borderRadius | double | 15.0 | 弹窗圆角 |
progressBarHeight | double | 3.0 | 进度条高度 |
iconSize | double | 64.0 | 成功/失败图标尺寸 |
progressValueColor | Color | 0xFF398BFF | 进度条填充色 |
successImagePath | String | assets/images/ic_success_big.png | 成功状态图标 |
failImagePath | String | assets/images/ic_fail_big.png | 失败状态图标 |
完整列表见 ota_dialog.dart。
API Reference
UpdatePage(StatefulWidget)
升级功能入口页面。
class UpdatePage extends StatefulWidget {
const UpdatePage({super.key});
State<UpdatePage> createState() => _UpdatePageState();
}
_UpdatePageState 关键方法
| 方法 | 说明 |
|---|---|
initState() | 装配管理器、注册 MethodChannel 回调、恢复上次选中文件路径 |
_initializeManagers() | 创建 OtaFileManager、DialogManager、PopupMenuManager、OtaConnectionManager |
build(context) | 从 Provider.of<DataNotifier> 读取 otaData,未开始升级时回填 _state/_deviceType,渲染状态栏、文件区与操作区 |
_handleMethodCall | 平台通道方法处理器(原生回调入口) |
_cleanOtaData | OtaConnectionManager 清理 OTA 数据后的回调,用于重置页面状态 |
_checkStorageEnvironment | Android 下首次添加文件前检查存储环境(Android 专用) |
_handleLocalAdd / _handleComputerTransfer / _handleScanDownload | 三种文件添加方式的处理器,由 PopupMenuManager 弹出的菜单触发 |
OtaDialog(StatefulWidget)
升级进度/结果弹窗。内部 _OtaDialogState 在 initState 调用 _startListeningToOtaState() 订阅 BleEventStream,通过 PopScope.canPop 控制关闭时机,按 _otaState 分别渲染「升级中」「重新连接」「完成(成功/失败)」三种内容。
ConnectionStateManager(单例 ChangeNotifier)
| 成员 | 签名 | 说明 |
|---|---|---|
| 构造 | factory ConnectionStateManager() | 返回全局唯一实例(懒加载单例) |
| 属性 | int get connectState | 当前连接状态值 |
| 方法 | void updateConnectState(int newState) | 更新状态;仅在变化时 notifyListeners() |
| 静态 | static int get currentState | 静态读取当前状态;实例为空时返回 AppConstants.connectionFailed |
OtaFileManager 构造回调
| 参数 | 类型 | 说明 |
|---|---|---|
otaFileList | List<Map<String, String>> | 文件列表引用(页面持有) |
onFileListUpdated | ValueChanged<List<Map<String, String>>> | 列表更新回调,页面内 setState |
onSelectedFileChanged | ValueChanged<String> | 选中文件变化回调;若重复点击同一文件则取消选中(置 null) |
Failure Modes, Edge Cases & Concurrency
升级过程中误触返回键
升级进行中(非 KEY_STATE_IDLE / ERROR)用户按返回键,PopScope.canPop = false,弹窗不会关闭,防止升级被打断。这是「升级不可中断」设计意图的直接体现(ota_dialog.dart)。
连接断开时的状态回填
build 阶段若 _state == AppConstants.connectionDisconnect,会强制将 _deviceType 置空(update_page.dart)。这是有意的边界处理:设备断开后,残留的设备类型信息对用户是误导,UI 上应只保留「未连接」状态。
升级中避免历史事件覆盖
build 中的状态回填受 !_isOtaStarted 保护。升级一旦开始,页面不再用 otaData 历史数据覆盖 _state/_deviceType;升级进度完全由 OtaDialog 独立订阅 BleEventStream 驱动。这避免了「页面重建 → 回填旧状态 → 与弹窗进度冲突」的并发一致性问题(update_page.dart)。
连接状态变更的竞态
ConnectionStateManager.updateConnectState 在值不变时直接返回、不通知监听者,从源头消除了「重复状态导致的多余重建」。同时 static currentState 提供无实例时的兜底值 AppConstants.connectionFailed,保证任何时刻读取都不为空(connection_state_manager.dart)。
Android 存储环境与权限
Android 平台首次点击「添加文件」时,_isStorageEnvironmentChecked == false 会先执行 _checkStorageEnvironment() 并直接 return,待用户完成存储授权后才能弹出添加菜单(update_page.dart)。页面还维护 _hasCameraPermission / _hasGalleryPermission,配合 permission_handler 处理扫码与相册权限,避免在无权限时崩溃。
失败原因与结果展示
_OtaDialogState._failureReason 预留了失败原因字段(当前为空字符串,见 ota_dialog.dart),失败态通过 _isSuccess = false 与 ic_fail_big.png 图标呈现;成功态则展示 ic_success_big.png。终态均允许用户关闭弹窗并返回页面继续操作。
Performance & Operational Notes
订阅生命周期
OtaDialog在initState中订阅BleEventStream(StreamSubscription? _otaStateSubscription),弹窗关闭后需要确保取消订阅,避免事件泄漏与重复渲染;升级数据清理时由OtaConnectionManager.onOtaDataCleaned回调页面执行_cleanOtaData复位。UpdatePage持有_otaFileListSubscription(StreamSubscription<List<Map<String, String>>>),文件列表流的订阅同样需要随页面销毁释放。
渲染性能
- 状态通过 Provider(
DataNotifier)与 ChangeNotifier(ConnectionStateManager)分发,只有数据变化才触发notifyListeners(),避免整页高频重建; - 进度条使用固定高度(3px)与单一填充色(
0xFF398BFF),进度更新仅作用于弹窗内部组件,不牵连整个页面树。
操作提示
- 升级操作属于关键路径,建议在真机上验证完整链路(查文件 → 传输 → 校验 → 成功/失败),并确认 BLE 连接稳定后再发起升级;
- 升级过程中 App 切后台或系统回收资源可能导致中断,生产环境应配合
BleEventConstants.ERROR终态做断点恢复或失败引导。
Extension Points
- 文件来源扩展:
UpdatePage的「本地添加 / 电脑传输 / 扫码下载」由PopupMenuManager.showAddFilePopupMenu统一弹出,新增来源只需扩展菜单项并实现对应的_handleXxx处理器; - 对话框扩展:
DialogManager集中了所有对话框的构建(OTA 弹窗、下载弹窗、权限确认等),新增对话框只需在DialogManager增加一个buildXxxDialog()方法; - 文件管理回调:
OtaFileManager通过onFileListUpdated/onSelectedFileChanged回调与 UI 解耦,可替换为其他列表管理实现(如数据库持久化)而不改页面; - 连接状态消费:
ConnectionStateManager是全局单例ChangeNotifier,任意页面或管理器都可addListener或静态读取currentState,适合扩展「连接状态变化 → 全局提示」等能力。
Related Links
- UpdatePage 源码
- OtaDialog 源码
- ConnectionStateManager 源码
- OtaConnectionManager 源码
- DialogManager 源码
- 设备连接与发现:参见设备页(
devices_page)相关文档 - 固件文件下载与分享:参见文件相关页面(
file_share_page、download_file_dialog)文档