山南市网站建设_网站建设公司_支付系统_seo优化
2026/1/16 11:17:13 网站建设 项目流程

示例图片在这里插入图片描述

引言

在边防巡检、电力抢修、野外勘探、基层政务等场景中,网络不可用是常态而非例外。然而,多数 OpenHarmony + Flutter 应用仍严重依赖在线服务,一旦断网即“瘫痪”——无法登录、不能提交表单、地图空白、数据丢失。

要构建真正高可靠的国产化应用,必须实现 全链路离线能力

  • 身份认证离线化(支持离线登录);
  • 业务数据本地持久化与同步;
  • 静态资源(UI、地图、文档)预置;
  • 网络恢复后自动回传队列。

本文将提供一套 端到端离线架构方案,结合 OpenHarmony 的分布式能力与 Flutter 的跨端优势,打造“有网增强、无网可用”的韧性应用,并附完整代码示例。


一、离线能力全景设计

┌───────────────────────────────────────────────────────┐
│                Flutter App (Dart)                     │
├───────────────┬───────────────┬───────────────────────┤
│ 离线登录      │ 本地数据库    │ 静态资源管理          │
│ - Token 缓存  │ - Hive / Moor │ - AssetBundle 预加载  │
│ - 生物认证    │ - 冲突解决    │ - 动态资源包下载      │
└───────▲───────┴───────▲───────┴───────────▲───────────┘│               │                   │▼               ▼                   ▼
┌───────────────────────────────────────────────────────┐
│           OpenHarmony 离线支撑层 (ArkTS)              │
├───────────────┬───────────────┬───────────────────────┤
│ @ohos.account │ @ohos.data.rdb│ @ohos.file.fs         │
│ .distributed  │ /relational   │                       │
│               │               │                       │
└───────▲───────┴───────▲───────┴───────────▲───────────┘│               │                   │▼               ▼                   ▼
┌───────────────────────────────────────────────────────┐
│            设备本地存储(SQLite / 文件系统)           │
│            + 分布式软总线(SoftBus)备用同步通道       │
└───────────────────────────────────────────────────────┘

核心理念所有关键功能必须能在无网络、无服务器情况下运行;网络仅用于增强与同步


二、离线登录:支持无网身份验证

问题

传统 JWT Token 过期后需联网刷新 → 断网即登出。

✅ 解决方案:长有效期 Token + 本地生物认证二次校验

步骤 1:登录时缓存凭证(Dart)
// lib/services/auth_service.dart
class AuthService {
static const String _tokenKey = 'offline_token';
static const String _userIdKey = 'user_id';
static const Duration _longExpiry = Duration(days: 30);
Future<void> login(String username, String password) async {// 1. 联网认证(首次)final response = await http.post('/api/login', body: {'username': username, 'password': password});if (response.statusCode == 200) {final data = jsonDecode(response.body);// 2. 保存长期 Token(加密存储,见前文安全篇)await SecureStorage().write(_tokenKey, data['token']);await SecureStorage().write(_userIdKey, data['userId']);// 3. 注册生物认证(如指纹)await BiometricAuth.register();}}// 离线登录:验证本地 Token + 生物特征Future<bool> offlineLogin() async {final token = await SecureStorage().read(_tokenKey);if (token == null) return false;// 检查 Token 是否在有效期内(宽松策略)final payload = Jwt.parse(token);if (DateTime.now().isAfter(payload.expiry.add(_longExpiry))) {return false; // 需重新联网}// 生物认证二次确认(防设备丢失)final authResult = await BiometricAuth.authenticate();return authResult.success;}}

安全提示:Token 存储需结合前文《安全加固》中的 TEE 加密方案。


三、本地数据库:结构化数据持久化

选型对比

方案优点缺点适用场景
Hive纯 Dart、零依赖、快无关系查询配置、缓存
Moor (Drift)SQL 支持、类型安全需 native 编译复杂业务数据
OpenHarmony RDB系统级、高性能需 ArkTS 封装高频读写

推荐组合Hive(轻量) + OpenHarmony RDB(核心业务)

示例:使用 OpenHarmony RDB 存储巡检记录(ArkTS)
// model/InspectionDb.ts
import relationalStore from '@ohos.data.relationalStore';
export class InspectionDb {
private store: relationalStore.RdbStore | null = null;
async init(context: any): Promise<void> {const config = relationalStore.createRdbStoreConfig('inspection.db');this.store = await relationalStore.getRdbStore(context, config);// 创建表await this.store.executeSql(`CREATE TABLE IF NOT EXISTS inspections (id TEXT PRIMARY KEY,location TEXT,status TEXT,timestamp INTEGER,synced BOOLEAN DEFAULT 0)`);}async saveInspection(inspection: any): Promise<void> {const values = new relationalStore.ValuesBucket();values.putString('id', inspection.id);values.putString('location', inspection.location);values.putString('status', inspection.status);values.putLong('timestamp', Date.now());values.putBoolean('synced', false);await this.store!.insert('inspections', values);}async getUnsyncedInspections(): Promise<any[]> {const resultSet = await this.store!.querySql('SELECT * FROM inspections WHERE synced = 0');const list: any[] = [];while (resultSet.goToNextRow()) {list.push({id: resultSet.getString(resultSet.getColumnIndex('id')),location: resultSet.getString(resultSet.getColumnIndex('location')),status: resultSet.getString(resultSet.getColumnIndex('status')),timestamp: resultSet.getLong(resultSet.getColumnIndex('timestamp'))});}resultSet.close();return list;}async markAsSynced(id: string): Promise<void> {const values = new relationalStore.ValuesBucket();values.putBoolean('synced', true);await this.store!.update(values, 'id = ?', [id]);}}
Dart 层调用(通过 MethodChannel)
// lib/repositories/inspection_repo.dart
class InspectionRepository {
static const _channel = MethodChannel('com.example.inspection_db');
Future<void> save(Inspection inspection) async {await _channel.invokeMethod('save', inspection.toJson());}Future<List<Inspection>> getUnsynced() async {final List<dynamic> rawList = await _channel.invokeMethod('getUnsynced');return rawList.map((e) => Inspection.fromJson(e)).toList();}Future<void> markSynced(String id) async {await _channel.invokeMethod('markSynced', {'id': id});}}

四、静态资源离线化:UI、地图、文档预置

1. Flutter Asset 预加载

将图片、字体、JSON 配置打包进 HAP:

# pubspec.yaml
flutter:
assets:
- assets/offline_maps/
- assets/forms/
- assets/icons/

运行时直接读取:

final ByteData data = await rootBundle.load('assets/forms/patrol_template.json');

2. 动态资源包按需下载

对超大资源(如城市离线地图),启动时检测并下载:

// lib/services/resource_manager.dart
class ResourceManager {
Future<void> ensureOfflineMap(String city) async {final file = File('/data/storage/el2/base/haps/entry/files/maps/$city.dat');if (!await file.exists()) {// 从内网 CDN 下载(有网时)final response = await http.get('http://intranet-cdn/maps/$city.dat');await file.writeAsBytes(response.bodyBytes);}}}

路径说明:OpenHarmony 应用私有目录为 /data/storage/el2/base/haps/entry/files/,无需额外权限。


五、网络状态感知与自动同步

步骤 1:监听网络变化(ArkTS)

// model/NetworkMonitor.ts
import net from '@ohos.net.connection';
export class NetworkMonitor {
private callback: () => void;
constructor(callback: () => void) {
this.callback = callback;
}
start(): void {
const conn = net.getDefaultNet();
conn.on('netAvailable', () => {
console.log(' 网络已恢复');
this.callback(); // 触发同步
});
conn.on('netUnavailable', () => {
console.log(' 网络断开');
});
}
}

步骤 2:Dart 层实现同步队列

// lib/services/sync_service.dart
class SyncService {
final InspectionRepository _repo = InspectionRepository();
Future<void> syncAll() async {final unsynced = await _repo.getUnsynced();for (final item in unsynced) {try {// 上传到服务器await http.post('/api/inspections', body: item.toJson());// 标记为已同步await _repo.markSynced(item.id);} catch (e) {// 网络再次中断?保留未同步状态break;}}}}// 在 main.dart 中监听void main() {runApp(MyApp());// 注册网络恢复回调const EventChannel('com.example.network/events').receiveBroadcastStream().listen((_) => SyncService().syncAll());}

六、利用 SoftBus 实现 P2P 离线协同(高级场景)

当多台设备同处无网环境(如野外作业队),可通过 OpenHarmony 软总线实现设备间数据交换:

// ArkTS: 发送未同步数据到附近设备
async function shareViaSoftBus(peerDeviceId: string) {
const unsynced = await inspectionDb.getUnsyncedInspections();
const message = JSON.stringify(unsynced);
await softbus.sendMessage(peerDeviceId, message); // 前文 SoftBus 插件
}

接收方解析后存入本地数据库,待任一设备联网即可统一回传。

价值:构建“去中心化”离线协作网络,极大提升野外作业效率。


七、测试与验证:模拟无网环境

1. DevEco Studio 网络控制

2. 自动化测试脚本

test('离线登录成功', () async {
// 模拟无网
HttpOverrides.runZoned(() {}, createHttpClient: (_) => MockHttpClient());
final success = await AuthService().offlineLogin();
expect(success, true);
});
class MockHttpClient extends HttpClient {

Future<HttpClientRequest> openUrl(String method, Uri url) {throw SocketException('No network'); // 强制断网}}

八、总结:离线能力 Checklist

能力是否实现验证方式
离线登录关闭网络后仍可进入主界面
本地数据存储重启应用后数据不丢失
静态资源可用无网时地图/表单正常显示
自动同步队列恢复网络后数据自动上传
P2P 协同(可选)⚠️多设备无网环境下数据互通

终极目标:用户完全感知不到“在线”与“离线”的边界——这才是真正的高可靠应用。

通过本文方案,你的 OpenHarmony + Flutter 应用将具备 军工级离线韧性,从容应对最严苛的野外与应急场景。


需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询