鸿蒙5跨设备同步:AGC云数据库实现多端数据共享实战

一、云数据库核心概念与配置
1.1 服务开通与准备
登录AppGallery Connect控制台
进入「构建」>「云数据库」服务
创建HarmonyOS应用对应的数据库实例
1.2 项目级配置
// 项目级build.gradle
buildscript {
repositories {
maven { url 'https://developer.huawei.com/repo/' }
}
dependencies {
classpath 'com.huawei.agconnect:agcp:1.6.5.300'
}
}
1.3 模块级依赖
dependencies {
implementation 'com.huawei.agconnect:agconnect-clouddb-harmony:1.6.5.300'
implementation 'com.huawei.agconnect:agconnect-auth-harmony:1.6.5.300'
}
二、数据模型设计与实现
2.1 定义对象类型
import com.huawei.agconnect.cloud.database.annotations.Indexes;
import com.huawei.agconnect.cloud.database.annotations.PrimaryKeys;
import com.huawei.agconnect.cloud.database.CloudDBZoneObject;
import com.huawei.agconnect.cloud.database.annotations.DefaultValue;
import com.huawei.agconnect.cloud.database.annotations.NotNull;

@PrimaryKeys({"id"})
@Indexes({"userId:userId", "updateTime:updateTime"})
public class SyncData extends CloudDBZoneObject {
@NotNull
private String id;

@NotNull
private String userId;

private String content;

@DefaultValue(stringValue = "text")
private String dataType;

private Long updateTime;

// 标准getter和setter方法
// 必须包含无参构造函数
public SyncData() {
    super(SyncData.class);
}

}
2.2 生成ORM代码
在模块级build.gradle中添加:

android {
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
}
}
}
}
执行Make Project后,AGC插件会自动生成必要的数据库操作类。

三、数据库初始化与同步配置
3.1 初始化云数据库
import com.huawei.agconnect.cloud.database.AGConnectCloudDB;
import com.huawei.agconnect.cloud.database.CloudDBZone;
import com.huawei.agconnect.cloud.database.CloudDBZoneConfig;
import ohos.app.Context;

public class CloudDBManager {
private static CloudDBZone mCloudDBZone;

public static void init(Context context) {
    // 初始化云数据库实例
    AGConnectCloudDB.initialize(context);
    
    // 创建数据库配置
    CloudDBZoneConfig config = new CloudDBZoneConfig(
        "SyncDBZone", // 自定义区名称
        CloudDBZoneConfig.CloudDBZoneSyncProperty.CLOUDDBZONE_CLOUD_CACHE,
        CloudDBZoneConfig.CloudDBZoneAccessProperty.CLOUDDBZONE_PUBLIC
    );
    
    // 设置数据同步模式
    config.setPersistenceEnabled(true);
    config.setSyncInterval(60); // 60秒同步间隔
    
    try {
        // 打开数据库区
        mCloudDBZone = AGConnectCloudDB.getInstance()
            .openCloudDBZone(config, true);
    } catch (Exception e) {
        Log.error("CloudDB", "初始化失败", e);
    }
}

public static CloudDBZone getCloudDBZone() {
    return mCloudDBZone;
}

}
四、数据操作实现
4.1 数据插入与更新
import com.huawei.agconnect.cloud.database.CloudDBZoneTask;
import com.huawei.agconnect.cloud.database.exceptions.CloudDBException;

public class DataSyncHelper {
public static void upsertData(SyncData data) {
CloudDBZoneTask task = CloudDBManager.getCloudDBZone()
.executeUpsert(data);

    task.addOnSuccessListener(affectedRows -> {
        Log.info("DataSync", "数据同步成功,影响行数: " + affectedRows);
    }).addOnFailureListener(e -> {
        if (e instanceof CloudDBException) {
            handleCloudDBError((CloudDBException)e);
        }
    });
}

private static void handleCloudDBError(CloudDBException e) {
    switch(e.getCode()) {
        case CloudDBException.CONFLICT:
            resolveDataConflict(e);
            break;
        case CloudDBException.NETWORK_UNAVAILABLE:
            cacheDataLocally();
            break;
        default:
            Log.error("CloudDB", "操作失败", e);
    }
}

}
4.2 数据查询
import com.huawei.agconnect.cloud.database.CloudDBZoneQuery;
import com.huawei.agconnect.cloud.database.CloudDBZoneSnapshot;

public class DataQueryHelper {
public static void queryUserData(String userId, DataCallback callback) {
// 构建查询条件
CloudDBZoneQuery query = CloudDBZoneQuery.where(SyncData.class)
.equalTo("userId", userId)
.orderByDesc("updateTime");

    // 执行查询
    CloudDBZoneTask<CloudDBZoneSnapshot<SyncData>> task = 
        CloudDBManager.getCloudDBZone().executeQuery(query);
        
    task.addOnSuccessListener(snapshot -> {
        List<SyncData> result = new ArrayList<>();
        while (snapshot.hasNext()) {
            SyncData data = snapshot.next();
            result.add(data);
        }
        snapshot.release();
        callback.onResult(result);
    });
}

public interface DataCallback {
    void onResult(List<SyncData> data);
}

}
五、实时数据同步
5.1 订阅数据变更
import com.huawei.agconnect.cloud.database.OnSnapshotListener;

public class RealtimeSyncManager {
private static CloudDBZoneTask<CloudDBZoneSnapshot> mSubscribeTask;

public static void startRealtimeSync(String userId) {
    // 创建查询条件
    CloudDBZoneQuery<SyncData> query = CloudDBZoneQuery.where(SyncData.class)
        .equalTo("userId", userId);
        
    // 创建监听器
    OnSnapshotListener<SyncData> listener = (snapshot, e) -> {
        if (e != null) {
            Log.error("RealtimeSync", "监听错误", e);
            return;
        }
        
        List<SyncData> changes = new ArrayList<>();
        while (snapshot.hasNext()) {
            SyncData data = snapshot.next();
            if (snapshot.isFromCloud()) {
                changes.add(data);
            }
        }
        snapshot.release();
        
        if (!changes.isEmpty()) {
            updateLocalUI(changes);
        }
    };
    
    // 执行订阅
    mSubscribeTask = CloudDBManager.getCloudDBZone()
        .subscribeSnapshot(query, listener);
}

public static void stopRealtimeSync() {
    if (mSubscribeTask != null) {
        mSubscribeTask.removeOnSuccessListener();
        mSubscribeTask.removeOnFailureListener();
    }
}

}
六、冲突解决策略
6.1 最后写入获胜策略
public class ConflictResolver {
public static void resolveConflict(SyncData local, SyncData cloud) {
// 比较更新时间
if (local.getUpdateTime() > cloud.getUpdateTime()) {
// 本地数据更新
cloud.setContent(local.getContent());
cloud.setUpdateTime(System.currentTimeMillis());
} else {
// 云端数据更新
local.setContent(cloud.getContent());
local.setUpdateTime(cloud.getUpdateTime());
}
}
}
6.2 自定义冲突处理
public class CustomConflictHandler implements CloudDBZone.ConflictHandler {
@Override
public Object onConflict(CloudDBZone.ConflictData conflictData) {
SyncData local = (SyncData)conflictData.getLocalObject();
SyncData cloud = (SyncData)conflictData.getServerObject();

    // 自定义合并逻辑
    if ("important".equals(local.getDataType())) {
        return local; // 重要数据优先使用本地
    } else {
        return cloud; // 其他情况使用云端
    }
}

}

// 使用自定义处理器
CloudDBZoneConfig config = new CloudDBZoneConfig(...);
config.setConflictHandler(new CustomConflictHandler());
七、离线缓存与同步
7.1 本地缓存实现
import ohos.data.rdb.RdbStore;
import ohos.data.rdb.ValuesBucket;

public class LocalCacheHelper {
private static final String TABLE_NAME = "sync_cache";
private final RdbStore mRdbStore;

public LocalCacheHelper(RdbStore rdbStore) {
    this.mRdbStore = rdbStore;
}

public void cacheData(SyncData data) {
    ValuesBucket values = new ValuesBucket();
    values.putString("id", data.getId());
    values.putString("content", data.getContent());
    values.putLong("update_time", System.currentTimeMillis());
    
    mRdbStore.insert(TABLE_NAME, values);
}

public void syncCacheToCloud() {
    // 查询所有未同步数据
    String sql = "SELECT * FROM " + TABLE_NAME + " WHERE synced = 0";
    ResultSet result = mRdbStore.querySql(sql);
    
    while (result.goToNextRow()) {
        SyncData data = new SyncData();
        data.setId(result.getString(result.getColumnIndexForName("id")));
        data.setContent(result.getString(result.getColumnIndexForName("content")));
        
        // 尝试同步
        CloudDBManager.getCloudDBZone().executeUpsert(data)
            .addOnSuccessListener(count -> {
                markAsSynced(data.getId());
            });
    }
    result.close();
}

}
八、完整示例:跨设备笔记同步应用
import ohos.agp.components.*;
import ohos.app.Ability;
import ohos.app.Context;

public class NoteSyncAbility extends Ability {
private TextField mInputField;
private ListContainer mNoteList;
private List mNotes = new ArrayList<>();

@Override
public void onStart(Intent intent) {
    super.onStart(intent);
    super.setUIContent(ResourceTable.Layout_note_sync_layout);
    
    // 初始化UI组件
    mInputField = (TextField) findComponentById(ResourceTable.Id_note_input);
    mNoteList = (ListContainer) findComponentById(ResourceTable.Id_note_list);
    
    // 设置按钮监听
    Button saveBtn = (Button) findComponentById(ResourceTable.Id_save_btn);
    saveBtn.setClickedListener(this::saveNote);
    
    // 初始化云数据库
    CloudDBManager.init(this);
    
    // 启动实时同步
    String userId = AuthManager.getCurrentUserId();
    RealtimeSyncManager.startRealtimeSync(userId);
    
    // 加载初始数据
    loadNotes(userId);
}

private void saveNote(Component component) {
    String content = mInputField.getText();
    if (content.isEmpty()) return;
    
    SyncData note = new SyncData();
    note.setId(UUID.randomUUID().toString());
    note.setUserId(AuthManager.getCurrentUserId());
    note.setContent(content);
    note.setDataType("note");
    note.setUpdateTime(System.currentTimeMillis());
    
    DataSyncHelper.upsertData(note);
    mInputField.setText("");
}

private void loadNotes(String userId) {
    DataQueryHelper.queryUserData(userId, new DataQueryHelper.DataCallback() {
        @Override
        public void onResult(List<SyncData> notes) {
            getUITaskDispatcher().asyncDispatch(() -> {
                mNotes.clear();
                mNotes.addAll(notes);
                refreshNoteList();
            });
        }
    });
}

private void refreshNoteList() {
    SimpleListAdapter<SyncData> adapter = new SimpleListAdapter<>(
        mNotes,
        (data, holder, position) -> {
            Text text = (Text) holder.getComponent();
            text.setText(data.getContent());
        },
        ResourceTable.Layout_note_item
    );
    mNoteList.setItemProvider(adapter);
}

@Override
protected void onBackground() {
    super.onBackground();
    // 应用进入后台时强制同步
    CloudDBManager.getCloudDBZone().executeSync();
}

@Override
protected void onStop() {
    super.onStop();
    RealtimeSyncManager.stopRealtimeSync();
}

}
九、性能优化与调试
9.1 批量操作优化
public class BatchOperationHelper {
public static void batchInsert(List dataList) {
CloudDBZoneTask task = CloudDBManager.getCloudDBZone()
.executeUpsert(dataList);

    task.addOnSuccessListener(count -> {
        Log.info("BatchInsert", "批量插入成功,影响行数: " + count);
    });
}

public static void batchDelete(List<String> ids) {
    CloudDBZoneQuery<SyncData> query = CloudDBZoneQuery.where(SyncData.class)
        .in("id", ids.toArray(new String[0]));
        
    CloudDBZoneTask<Integer> task = CloudDBManager.getCloudDBZone()
        .executeDelete(query);
}

}
9.2 调试工具类
import com.huawei.agconnect.cloud.database.CloudDBZoneObject;
import com.huawei.agconnect.cloud.database.CloudDBZoneSchema;

public class CloudDBDebugger {
public static void printSchemaInfo() {
CloudDBZoneSchema schema = CloudDBManager.getCloudDBZone().getCloudDBZoneSchema();
Log.debug("Schema", "对象类型列表: " + schema.getObjectTypeNames());

    for (String typeName : schema.getObjectTypeNames()) {
        Class<? extends CloudDBZoneObject> clazz = schema.getObjectType(typeName);
        Log.debug("Schema", typeName + " 字段: " + Arrays.toString(clazz.getDeclaredFields()));
    }
}

public static void monitorSyncStatus() {
    CloudDBManager.getCloudDBZone().setSyncStatusListener((status, estimate) -> {
        Log.info("SyncStatus", "同步状态: " + status + 
                ", 预计剩余时间: " + estimate + "ms");
    });
}

}
十、最佳实践建议
​​数据模型设计原则​​:
// 使用组合键提高查询效率
@PrimaryKeys({"userId", "itemId"})
public class UserItem extends CloudDBZoneObject {
@NotNull
private String userId;

@NotNull
private String itemId;

// 其他字段...

}
​​网络状态处理​​:
public class NetworkAwareSync {
public static void syncWithRetry(SyncData data) {
if (NetworkUtil.isConnected()) {
DataSyncHelper.upsertData(data);
} else {
LocalCacheHelper.cacheData(data);
NetworkUtil.registerConnectionListener(new NetworkUtil.ConnectionListener() {
@Override
public void onConnected() {
syncCachedData();
}
});
}
}
}
​​安全规则配置​​:
// AGC控制台的安全规则配置示例
{
"rules": {
"SyncData": {
".read": "auth != null && query.equalTo('userId', auth.uid)",
".write": "auth != null && data.userId == auth.uid",
".index": ["userId", "updateTime"]
}
}
}
结语
通过AGC云数据库服务,HarmonyOS 5应用可以实现:

​​无缝跨设备体验​​:用户数据在手机、平板、智慧屏等设备间自动同步
​​离线可用性​​:本地缓存确保弱网环境下正常使用
​​实时协作能力​​:多用户数据变更即时可见
建议开发者:

合理设计数据模型,平衡查询效率与存储成本
根据业务场景选择合适的同步策略(立即同步/延迟同步)
监控云数据库使用量,优化查询性能
将云数据库与AGC其他服务(如认证、函数计算)结合,可以构建更强大的跨设备协同应用。随着HarmonyOS设备生态的扩展,这种云端同步能力将变得愈发重要。

posted @ 2025-06-28 22:58  暗雨YA  阅读(46)  评论(0)    收藏  举报