Flutter & OpenHarmony 运动App运动数据同步组件开发

前言

运动数据同步是确保用户数据安全和多设备访问的核心功能。通过云端同步,用户可以在更换设备后恢复数据,也可以在多个设备上查看同一份运动记录。本文将详细介绍如何在Flutter与OpenHarmony平台上实现可靠的运动数据同步组件,包括增量同步、冲突处理、离线支持、同步状态管理等功能模块的完整实现方案。

Flutter同步数据模型

dart 复制代码
class SyncRecord {
  final String id;
  final String type;
  final Map<String, dynamic> data;
  final DateTime modifiedAt;
  final bool isSynced;
  final int version;
  
  SyncRecord({
    required this.id,
    required this.type,
    required this.data,
    required this.modifiedAt,
    this.isSynced = false,
    this.version = 1,
  });
  
  Map<String, dynamic> toJson() => {
    'id': id,
    'type': type,
    'data': data,
    'modifiedAt': modifiedAt.toIso8601String(),
    'version': version,
  };
}

class SyncStatus {
  final DateTime? lastSyncTime;
  final int pendingCount;
  final bool isSyncing;
  final String? error;
  
  SyncStatus({this.lastSyncTime, this.pendingCount = 0, this.isSyncing = false, this.error});
  
  String get statusText {
    if (isSyncing) return '同步中...';
    if (error != null) return '同步失败';
    if (pendingCount > 0) return '待同步 $pendingCount 条';
    if (lastSyncTime != null) return '已同步';
    return '未同步';
  }
}

同步数据模型定义了可同步记录的结构。每条记录包含唯一ID、类型、数据内容、修改时间、同步状态和版本号。version用于冲突检测,当服务器版本高于本地版本时需要处理冲突。SyncStatus封装同步状态信息,包括最后同步时间、待同步数量、是否正在同步和错误信息。statusText属性根据状态返回用户友好的文字描述。

OpenHarmony网络同步服务

typescript 复制代码
import http from '@ohos.net.http';

class CloudSyncService {
  private baseUrl: string = 'https://api.fitness.com/sync';
  
  async uploadRecords(records: Array<object>, userId: string): Promise<object> {
    let httpRequest = http.createHttp();
    
    try {
      let response = await httpRequest.request(
        `${this.baseUrl}/upload`,
        {
          method: http.RequestMethod.POST,
          header: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${userId}`,
          },
          extraData: JSON.stringify({ records: records }),
        }
      );
      
      if (response.responseCode === 200) {
        return JSON.parse(response.result as string);
      }
      throw new Error('上传失败');
    } finally {
      httpRequest.destroy();
    }
  }
  
  async downloadRecords(userId: string, lastSyncTime: string): Promise<Array<object>> {
    let httpRequest = http.createHttp();
    
    try {
      let response = await httpRequest.request(
        `${this.baseUrl}/download?since=${lastSyncTime}`,
        {
          method: http.RequestMethod.GET,
          header: { 'Authorization': `Bearer ${userId}` },
        }
      );
      
      if (response.responseCode === 200) {
        let result = JSON.parse(response.result as string);
        return result['records'] || [];
      }
      return [];
    } finally {
      httpRequest.destroy();
    }
  }
  
  async getServerVersion(recordId: string): Promise<number> {
    // 获取服务器端记录版本
    return 0;
  }
}

网络同步服务处理与云端的数据交互。uploadRecords方法批量上传本地记录到服务器,使用POST请求发送JSON数据。downloadRecords方法从服务器下载指定时间之后修改的记录,实现增量同步。lastSyncTime参数确保只下载新数据,减少传输量。Authorization头携带用户身份信息。这种设计支持双向同步,本地修改上传到云端,云端修改下载到本地。

Flutter同步管理器

dart 复制代码
class SyncManager extends ChangeNotifier {
  SyncStatus _status = SyncStatus();
  List<SyncRecord> _pendingRecords = [];
  DateTime? _lastSyncTime;
  
  SyncStatus get status => _status;
  
  Future<void> addPendingRecord(SyncRecord record) async {
    _pendingRecords.add(record);
    _status = SyncStatus(
      lastSyncTime: _lastSyncTime,
      pendingCount: _pendingRecords.length,
    );
    notifyListeners();
  }
  
  Future<void> sync() async {
    if (_status.isSyncing) return;
    
    _status = SyncStatus(
      lastSyncTime: _lastSyncTime,
      pendingCount: _pendingRecords.length,
      isSyncing: true,
    );
    notifyListeners();
    
    try {
      // 上传本地修改
      if (_pendingRecords.isNotEmpty) {
        await _uploadPendingRecords();
      }
      
      // 下载服务器修改
      await _downloadServerChanges();
      
      _lastSyncTime = DateTime.now();
      _status = SyncStatus(lastSyncTime: _lastSyncTime, pendingCount: 0);
    } catch (e) {
      _status = SyncStatus(
        lastSyncTime: _lastSyncTime,
        pendingCount: _pendingRecords.length,
        error: e.toString(),
      );
    }
    notifyListeners();
  }
  
  Future<void> _uploadPendingRecords() async {
    // 上传待同步记录
  }
  
  Future<void> _downloadServerChanges() async {
    // 下载服务器变更
  }
}

同步管理器协调整个同步流程。addPendingRecord方法将新修改的记录加入待同步队列。sync方法执行完整的同步流程:先上传本地修改,再下载服务器变更。使用isSyncing标志防止重复同步。同步过程中更新状态并通知监听者,UI可以显示同步进度。异常处理确保同步失败时记录错误信息,用户可以稍后重试。

Flutter同步状态组件

dart 复制代码
class SyncStatusWidget extends StatelessWidget {
  final SyncStatus status;
  final VoidCallback onSync;
  
  const SyncStatusWidget({Key? key, required this.status, required this.onSync}) : super(key: key);
  
  @override
  Widget build(BuildContext context) {
    return ListTile(
      leading: Icon(
        status.isSyncing ? Icons.sync : (status.error != null ? Icons.sync_problem : Icons.cloud_done),
        color: status.error != null ? Colors.red : Colors.green,
      ),
      title: Text(status.statusText),
      subtitle: status.lastSyncTime != null
          ? Text('上次同步: ${_formatTime(status.lastSyncTime!)}')
          : null,
      trailing: status.isSyncing
          ? SizedBox(width: 24, height: 24, child: CircularProgressIndicator(strokeWidth: 2))
          : IconButton(icon: Icon(Icons.refresh), onPressed: onSync),
    );
  }
  
  String _formatTime(DateTime time) {
    return '${time.month}/${time.day} ${time.hour}:${time.minute.toString().padLeft(2, '0')}';
  }
}

同步状态组件显示当前的同步状态。图标根据状态变化:同步中显示旋转图标,失败显示警告图标,成功显示云完成图标。显示状态文字和上次同步时间。右侧按钮触发手动同步,同步中时显示进度指示器。这种组件让用户随时了解数据同步情况,并可以手动触发同步。

OpenHarmony离线队列服务

typescript 复制代码
import dataPreferences from '@ohos.data.preferences';

class OfflineQueueService {
  private preferences: dataPreferences.Preferences | null = null;
  
  async initialize(context: Context): Promise<void> {
    this.preferences = await dataPreferences.getPreferences(context, 'sync_queue');
  }
  
  async addToQueue(record: object): Promise<void> {
    if (this.preferences) {
      let queueJson = await this.preferences.get('queue', '[]') as string;
      let queue: Array<object> = JSON.parse(queueJson);
      queue.push(record);
      await this.preferences.put('queue', JSON.stringify(queue));
      await this.preferences.flush();
    }
  }
  
  async getQueue(): Promise<Array<object>> {
    if (this.preferences) {
      let queueJson = await this.preferences.get('queue', '[]') as string;
      return JSON.parse(queueJson);
    }
    return [];
  }
  
  async clearQueue(): Promise<void> {
    if (this.preferences) {
      await this.preferences.put('queue', '[]');
      await this.preferences.flush();
    }
  }
  
  async removeFromQueue(recordId: string): Promise<void> {
    if (this.preferences) {
      let queue = await this.getQueue();
      queue = queue.filter((r: object) => r['id'] !== recordId);
      await this.preferences.put('queue', JSON.stringify(queue));
      await this.preferences.flush();
    }
  }
}

离线队列服务在网络不可用时缓存待同步数据。addToQueue方法将记录加入队列,getQueue方法获取所有待同步记录。网络恢复后,同步管理器从队列中取出记录进行上传,成功后调用removeFromQueue移除。clearQueue方法在全部同步成功后清空队列。这种离线支持确保用户在没有网络时也能正常使用应用,数据不会丢失。

Flutter冲突解决组件

dart 复制代码
class ConflictResolutionDialog extends StatelessWidget {
  final SyncRecord localRecord;
  final SyncRecord serverRecord;
  final Function(SyncRecord) onResolved;
  
  const ConflictResolutionDialog({
    Key? key,
    required this.localRecord,
    required this.serverRecord,
    required this.onResolved,
  }) : super(key: key);
  
  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: Text('数据冲突'),
      content: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Text('该记录在本地和服务器都有修改,请选择保留哪个版本:'),
          SizedBox(height: 16),
          _buildVersionCard('本地版本', localRecord.modifiedAt, () => onResolved(localRecord)),
          SizedBox(height: 8),
          _buildVersionCard('服务器版本', serverRecord.modifiedAt, () => onResolved(serverRecord)),
        ],
      ),
    );
  }
  
  Widget _buildVersionCard(String title, DateTime time, VoidCallback onSelect) {
    return Card(
      child: ListTile(
        title: Text(title),
        subtitle: Text('修改时间: ${time.toString().substring(0, 19)}'),
        trailing: ElevatedButton(onPressed: onSelect, child: Text('选择')),
      ),
    );
  }
}

冲突解决组件在检测到数据冲突时让用户选择保留哪个版本。显示本地版本和服务器版本的修改时间,用户可以根据时间判断哪个是最新的修改。选择后调用onResolved回调,同步管理器使用选中的版本覆盖另一个。这种手动冲突解决方式确保用户不会意外丢失重要数据。

Flutter自动同步设置

dart 复制代码
class AutoSyncSettings extends StatefulWidget {
  final bool autoSyncEnabled;
  final bool wifiOnly;
  final Function(bool, bool) onSettingsChanged;
  
  const AutoSyncSettings({
    Key? key,
    required this.autoSyncEnabled,
    required this.wifiOnly,
    required this.onSettingsChanged,
  }) : super(key: key);
  
  @override
  State<AutoSyncSettings> createState() => _AutoSyncSettingsState();
}

class _AutoSyncSettingsState extends State<AutoSyncSettings> {
  late bool _autoSync;
  late bool _wifiOnly;
  
  @override
  void initState() {
    super.initState();
    _autoSync = widget.autoSyncEnabled;
    _wifiOnly = widget.wifiOnly;
  }
  
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        SwitchListTile(
          title: Text('自动同步'),
          subtitle: Text('运动结束后自动同步数据'),
          value: _autoSync,
          onChanged: (value) {
            setState(() => _autoSync = value);
            widget.onSettingsChanged(_autoSync, _wifiOnly);
          },
        ),
        SwitchListTile(
          title: Text('仅WiFi同步'),
          subtitle: Text('仅在WiFi网络下自动同步'),
          value: _wifiOnly,
          onChanged: _autoSync ? (value) {
            setState(() => _wifiOnly = value);
            widget.onSettingsChanged(_autoSync, _wifiOnly);
          } : null,
        ),
      ],
    );
  }
}

自动同步设置让用户配置同步行为。自动同步开关控制是否在运动结束后自动上传数据。仅WiFi同步选项避免消耗移动数据流量,只有自动同步开启时才可用。这种设置给用户足够的控制权,满足不同用户的需求。

总结

本文全面介绍了Flutter与OpenHarmony平台上运动数据同步组件的实现方案。从数据模型到网络服务,从同步管理到离线支持,从冲突处理到自动同步,涵盖了数据同步功能的各个方面。通过可靠的同步机制,我们可以确保用户的运动数据安全,支持多设备访问,提升用户体验。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

相关推荐
纟 冬2 小时前
Flutter & OpenHarmony 运动App运动模式选择组件开发
android·java·flutter
w139548564223 小时前
Flutter跨平台开发鸿蒙化JS-Dart通信桥接组件使用指南
javascript·flutter·harmonyos
2501_944446005 小时前
Flutter&OpenHarmony文本输入组件开发
前端·javascript·flutter
2501_946233896 小时前
Flutter与OpenHarmony大师详情页面实现
android·javascript·flutter
纟 冬7 小时前
Flutter & OpenHarmony 运动App运动目标设定组件开发
开发语言·javascript·flutter
2501_944446007 小时前
Flutter&OpenHarmony应用内导航与路由管理
开发语言·javascript·flutter
纟 冬7 小时前
Flutter & OpenHarmony 运动App运动挑战组件开发
flutter
2501_946233897 小时前
Flutter与OpenHarmony Tab切换组件开发详解
android·javascript·flutter
2501_946233897 小时前
Flutter与OpenHarmony订单详情页面实现
android·javascript·flutter