移动应用离线同步与冲突解决 mobile-offline-support

这项技能专注于开发支持离线功能的移动应用,实现数据的本地存储、同步队列管理和冲突解决,确保在无网络连接时的用户体验和数据一致性,关键词包括移动应用、离线、同步、冲突解决、本地存储、队列管理、网络切换。

移动开发 0 次安装 4 次浏览 更新于 3/7/2026

name: mobile-offline-support description: 离线优先移动应用,具有本地存储、同步队列、冲突解决功能。用于离线功能、数据同步、连接性处理、或遇到同步冲突、队列管理、存储限制、网络切换错误。

移动离线支持

构建离线优先移动应用,具有本地存储和同步功能。

React Native 实现

import AsyncStorage from '@react-native-async-storage/async-storage';
import NetInfo from '@react-native-community/netinfo';

class OfflineManager {
  constructor() {
    this.syncQueue = [];
    this.isOnline = true;
    // 同步队列中最大项目数,超出时丢弃最旧的项目
    this.MAX_SYNC_QUEUE_LENGTH = 1000;

    NetInfo.addEventListener(state => {
      this.isOnline = state.isConnected;
      if (this.isOnline) this.processQueue();
    });
  }

  /**
   * 从服务器获取数据。
   * TODO: 替换为实际的 API 端点实现。
   */
  async fetchFromServer(key) {
    try {
      // 示例实现 - 替换为您的 API
      const response = await fetch(`${API_BASE_URL}/data/${key}`);
      if (!response.ok) {
        throw new Error(`服务器返回 ${response.status}`);
      }
      return await response.json();
    } catch (error) {
      console.error('fetchFromServer 失败:', error);
      throw new Error(`获取 ${key} 失败: ${error.message}`);
    }
  }

  /**
   * 同步数据到服务器。
   * TODO: 替换为实际的 API 端点实现。
   */
  async syncToServer(key, data) {
    try {
      // 示例实现 - 替换为您的 API
      const response = await fetch(`${API_BASE_URL}/data/${key}`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data)
      });
      if (!response.ok) {
        throw new Error(`服务器返回 ${response.status}`);
      }
      return await response.json();
    } catch (error) {
      console.error('syncToServer 失败:', error);
      throw new Error(`同步 ${key} 失败: ${error.message}`);
    }
  }

  async getData(key) {
    const cached = await AsyncStorage.getItem(key);
    if (cached) return JSON.parse(cached);

    if (this.isOnline) {
      const data = await this.fetchFromServer(key);
      await AsyncStorage.setItem(key, JSON.stringify(data));
      return data;
    }

    return null;
  }

  async saveData(key, data) {
    await AsyncStorage.setItem(key, JSON.stringify(data));

    if (this.isOnline) {
      await this.syncToServer(key, data);
    } else {
      // 添加到队列
      this.syncQueue.push({ key, data, timestamp: Date.now() });

      // 强制执行队列边界 - 超出时丢弃最旧的项目
      while (this.syncQueue.length > this.MAX_SYNC_QUEUE_LENGTH) {
        const discarded = this.syncQueue.shift();
        console.warn(`同步队列已满 - 丢弃最旧项目: ${discarded.key}`);
      }

      // 持久化修剪后的队列
      await AsyncStorage.setItem('syncQueue', JSON.stringify(this.syncQueue));
    }
  }

  async processQueue() {
    const failedItems = [];
    for (const item of this.syncQueue) {
      try {
        await this.syncToServer(item.key, item.data);
      } catch (err) {
        console.error('同步失败:', err);
        failedItems.push(item);
      }
    }
    this.syncQueue = failedItems;
    if (failedItems.length === 0) {
      await AsyncStorage.removeItem('syncQueue');
    } else {
      await AsyncStorage.setItem('syncQueue', JSON.stringify(failedItems));
    }
  }
}

冲突解决

function resolveConflict(local, server) {
  // 最后写入者胜出
  if (local.updatedAt > server.updatedAt) return local;
  return server;

  // 或者合并更改
  // return { ...server, ...local };
}

UI 指示器

function OfflineIndicator() {
  const [isOnline, setIsOnline] = useState(true);

  useEffect(() => {
    return NetInfo.addEventListener(state => {
      setIsOnline(state.isConnected);
    });
  }, []);

  if (isOnline) return null;

  return (
    <View style={styles.banner}>
      <Text>您处于离线状态。更改将在连接时同步。</Text>
    </View>
  );
}

最佳实践

  • 本地缓存频繁访问的数据
  • 队列操作以进行后续同步
  • 显示清晰的离线指示器
  • 优雅地处理同步冲突
  • 压缩存储的数据
  • 彻底测试离线场景

原生实现

参见 references/native-implementations.md 以了解:

  • iOS Core Data 与同步管理器
  • Android Room 数据库与 WorkManager 同步

避免

  • 假设连接性
  • 在同步失败时丢失数据
  • 无限制的队列增长
  • 不安全地同步敏感数据