鸿蒙5离线数据处理:AGC云数据库的同步策略详解
一、AGC云数据库与离线同步概述
- AGC云数据库核心特性
AGC(AppGallery Connect)云数据库提供:
实时同步:设备间数据自动同步
离线优先:无网络时本地操作,恢复连接后自动同步
多端一致:跨设备数据一致性保障
安全规则:细粒度的数据访问控制
2. 离线同步工作原理
graph LR
A[本地操作] --> B[本地数据库]
B --> C{网络可用?}
C -->|是| D[同步到云端]
C -->|否| E[队列缓存]
D --> F[其他设备同步]
二、环境配置与初始化
- 添加依赖
在entry/build.gradle中配置:
dependencies {
// AGC核心
implementation 'com.huawei.agconnect:agconnect-core-harmony:1.6.5.300'
// 云数据库
implementation 'com.huawei.agconnect:agconnect-clouddb-harmony:1.6.5.300'
// 认证服务(可选)
implementation 'com.huawei.agconnect:agconnect-auth-harmony:1.6.5.300'
}
2. 初始化云数据库
创建CloudDBManager.ets:
import clouddb from '@hw-agconnect/clouddb';
import agconnect from '@hw-agconnect/core';
export class CloudDBManager {
private static instance: CloudDBManager | null = null;
private cloudDB: clouddb.CloudDBZone | null = null;
private constructor() {}
public static getInstance(): CloudDBManager {
if (!CloudDBManager.instance) {
CloudDBManager.instance = new CloudDBManager();
}
return CloudDBManager.instance;
}
// 初始化云数据库
async initialize(): Promise<void> {
try {
// 1. 初始化AGC
agconnect.instance().init();
// 2. 创建CloudDB实例
const cloudDBZoneConfig = new clouddb.CloudDBZoneConfig(
'QuickStartDemo', // 数据库名称
clouddb.CloudDBZoneSyncProperty.CLOUDDBZONE_CLOUD_CACHE, // 同步策略
clouddb.CloudDBZoneAccessProperty.CLOUDDBZONE_PUBLIC // 访问权限
);
// 3. 打开数据库
this.cloudDB = await clouddb.CloudDBZone.open(cloudDBZoneConfig);
console.log('CloudDB初始化成功');
} catch (error) {
console.error('CloudDB初始化失败:', error);
throw error;
}
}
// 获取数据库实例
getCloudDB(): clouddb.CloudDBZone {
if (!this.cloudDB) {
throw new Error('CloudDB未初始化');
}
return this.cloudDB;
}
}
三、数据模型定义与同步策略
- 定义对象类型
创建model/BookInfo.ets:
@Class
export class BookInfo {
@Field()
id: string = '';
@Field({ isIndex: true })
bookName: string = '';
@Field()
author: string = '';
@Field()
price: number = 0;
@Field({ isLocal: true }) // 标记为本地字段,不同步
lastReadTime: number = 0;
@Field({ isNeedEncrypt: true }) // 加密字段
secretNote: string = '';
@Field()
@PrimaryKey()
get primaryKey(): string {
return this.id;
}
}
2. 注册对象类型
在CloudDBManager中添加:
private objectTypes = [BookInfo];
async initialize(): Promise
// ...原有代码...
// 注册对象类型
await clouddb.CloudDBZone.registerObjectClass(
this.objectTypes.map(type => type.name)
);
console.log('对象类型注册成功');
}
四、离线数据操作实现
-
新增数据(离线优先)
// 在CloudDBManager中添加
async addBook(book: BookInfo): Promise{
try {
const db = this.getCloudDB();
book.id = this.generateId(); // 生成唯一ID// 设置最后阅读时间(本地字段) book.lastReadTime = new Date().getTime(); // 执行插入 await db.executeUpsert([book]); console.log('书籍添加成功:', book.id);} catch (error) {
console.error('添加书籍失败:', error);
throw error;
}
}
private generateId(): string {
return 'book_' + Math.random().toString(36).substr(2, 9);
}
2. 查询数据(本地缓存优先)
// 在CloudDBManager中添加
async queryBooks(
conditions?: clouddb.CloudDBZoneQuery
policy: clouddb.CloudDBZoneQueryPolicy = clouddb.CloudDBZoneQueryPolicy.POLICY_QUERY_FROM_CLOUD_ONLY
): Promise<BookInfo[]> {
try {
const db = this.getCloudDB();
// 默认查询所有书籍
const query = conditions || clouddb.CloudDBZoneQuery.where(BookInfo);
// 执行查询
const snapshot = await db.executeQuery(
query,
policy // 查询策略
);
// 获取结果
const books: BookInfo[] = [];
while (snapshot.hasNext()) {
books.push(snapshot.next());
}
snapshot.release();
return books;
} catch (error) {
console.error('查询书籍失败:', error);
throw error;
}
}
3. 更新与删除操作
// 在CloudDBManager中添加
async updateBook(book: BookInfo): Promise
try {
const db = this.getCloudDB();
book.lastReadTime = new Date().getTime();
await db.executeUpsert([book]);
console.log('书籍更新成功:', book.id);
} catch (error) {
console.error('更新书籍失败:', error);
throw error;
}
}
async deleteBook(bookId: string): Promise
try {
const db = this.getCloudDB();
const book = new BookInfo();
book.id = bookId;
await db.executeDelete([book]);
console.log('书籍删除成功:', bookId);
} catch (error) {
console.error('删除书籍失败:', error);
throw error;
}
}
五、同步策略与冲突解决
-
同步策略配置
策略类型 说明 适用场景
CLOUDDBZONE_LOCAL_ONLY 仅本地操作 临时数据
CLOUDDBZONE_CLOUD_CACHE 本地优先,自动同步 大多数场景
CLOUDDBZONE_CLOUD_ONLY 仅云端操作 强一致性要求 -
冲突解决策略
// 在CloudDBManager中添加
async syncWithConflictResolution(): Promise{
try {
const db = this.getCloudDB();// 1. 获取未同步操作 const pendingWrites = await db.getPendingWrites(); // 2. 处理冲突 for (const write of pendingWrites) { try { // 尝试同步 await db.executeUpsert([write.object]); // 同步成功后删除本地记录 await db.removePendingWrite(write); } catch (syncError) { console.warn(`同步冲突: ${write.object.id}`, syncError); // 冲突处理方案1:使用服务器版本 const serverVersion = await this.queryBookFromServer(write.object.id); await db.executeUpsert([serverVersion]); // 冲突处理方案2:合并字段(自定义逻辑) // this.mergeConflict(write.object, serverVersion); // 标记为已处理 await db.removePendingWrite(write); } }} catch (error) {
console.error('同步处理失败:', error);
}
}
private async queryBookFromServer(bookId: string): Promise
const db = this.getCloudDB();
const query = clouddb.CloudDBZoneQuery.where(BookInfo)
.equalTo('id', bookId);
const snapshot = await db.executeQuery(
query,
clouddb.CloudDBZoneQueryPolicy.POLICY_QUERY_FROM_CLOUD_ONLY
);
if (snapshot.hasNext()) {
return snapshot.next();
}
throw new Error('未找到书籍');
}
六、网络状态监听与自动同步
- 网络状态监听
创建NetworkManager.ets:
import connection from '@ohos.net.connection';
export class NetworkManager {
private static instance: NetworkManager | null = null;
private netHandle: connection.NetHandle;
private constructor() {
this.netHandle = connection.getDefaultNet();
}
public static getInstance(): NetworkManager {
if (!NetworkManager.instance) {
NetworkManager.instance = new NetworkManager();
}
return NetworkManager.instance;
}
// 检查网络状态
isConnected(): boolean {
try {
return this.netHandle.hasInternet();
} catch (error) {
console.error('检查网络状态失败:', error);
return false;
}
}
// 监听网络变化
onNetworkChange(callback: (connected: boolean) => void): void {
connection.on('netAvailable', (data: { netHandle: connection.NetHandle }) => {
callback(data.netHandle.hasInternet());
});
connection.on('netUnavailable', () => {
callback(false);
});
}
}
2. 自动同步策略实现
在CloudDBManager中添加:
private syncInterval: number = 0;
private isSyncing: boolean = false;
// 启动自动同步
startAutoSync(interval: number = 30000): void {
this.syncInterval = interval;
this.setupNetworkListener();
this.runSyncLoop();
}
private setupNetworkListener(): void {
NetworkManager.getInstance().onNetworkChange(async (connected) => {
if (connected) {
console.log('网络恢复,触发同步');
await this.syncData();
}
});
}
private async runSyncLoop(): Promise
while (this.syncInterval > 0) {
await new Promise(resolve => setTimeout(resolve, this.syncInterval));
if (NetworkManager.getInstance().isConnected() && !this.isSyncing) {
await this.syncData();
}
}
}
private async syncData(): Promise
if (this.isSyncing) return;
this.isSyncing = true;
try {
console.log('开始数据同步...');
// 1. 同步本地更改到云端
await this.syncWithConflictResolution();
// 2. 从云端获取最新数据
await this.pullLatestData();
console.log('数据同步完成');
} catch (error) {
console.error('同步过程中出错:', error);
} finally {
this.isSyncing = false;
}
}
private async pullLatestData(): Promise
try {
// 示例:同步所有书籍数据
const db = this.getCloudDB();
const query = clouddb.CloudDBZoneQuery.where(BookInfo);
// 使用POLICY_QUERY_FROM_CLOUD_ONLY强制从云端获取
await db.executeQuery(
query,
clouddb.CloudDBZoneQueryPolicy.POLICY_QUERY_FROM_CLOUD_ONLY
);
} catch (error) {
console.error('拉取最新数据失败:', error);
throw error;
}
}
七、实战案例:离线优先的阅读应用
-
页面实现:图书列表
@Entry
@Component
struct BookListPage {
@State books: BookInfo[] = [];
@State loading: boolean = true;
@State networkStatus: string = '检查中...';private cloudDB = CloudDBManager.getInstance();
onPageShow() {
this.loadBooks();
this.checkNetwork();
}async loadBooks() {
this.loading = true;
try {
// 优先从本地缓存查询
this.books = await this.cloudDB.queryBooks(
undefined,
clouddb.CloudDBZoneQueryPolicy.POLICY_QUERY_FROM_LOCAL_ONLY
);// 网络可用时同步最新数据 if (NetworkManager.getInstance().isConnected()) { const cloudBooks = await this.cloudDB.queryBooks(); this.books = cloudBooks; } } catch (error) { console.error('加载书籍失败:', error); } finally { this.loading = false; }}
async checkNetwork() {
const isConnected = NetworkManager.getInstance().isConnected();
this.networkStatus = isConnected ? '已连接' : '离线模式';
}build() {
Column() {
Text('我的书库')
.fontSize(24)
.margin(10);Text(`状态: ${this.networkStatus}`) .fontColor(this.networkStatus === '离线模式' ? Color.Red : Color.Green); if (this.loading) { LoadingProgress() .margin(20); } else { List({ space: 10 }) { ForEach(this.books, (book: BookInfo) => { ListItem() { BookItem({ book: book }) } }) } .width('100%') .height('80%') } } .width('100%') .height('100%')}
}
@Component
struct BookItem {
@Prop book: BookInfo;
build() {
Row() {
Column() {
Text(this.book.bookName)
.fontSize(18);
Text(this.book.author)
.fontSize(14)
.fontColor(Color.Gray);
}
.margin(10)
Text(`¥${this.book.price.toFixed(2)}`)
.fontSize(16)
.fontColor(Color.Blue)
.margin({ right: 15 })
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
}
}
2. 页面实现:添加/编辑图书
@Entry
@Component
struct BookEditPage {
@State book: BookInfo = new BookInfo();
@State isNew: boolean = true;
@State saving: boolean = false;
private cloudDB = CloudDBManager.getInstance();
onPageShow() {
const params = router.getParams();
if (params && params.book) {
this.book = params.book;
this.isNew = false;
}
}
async saveBook() {
this.saving = true;
try {
if (this.isNew) {
await this.cloudDB.addBook(this.book);
} else {
await this.cloudDB.updateBook(this.book);
}
// 返回并刷新列表
router.back();
} catch (error) {
console.error('保存失败:', error);
} finally {
this.saving = false;
}
}
build() {
Column({ space: 15 }) {
Text(this.isNew ? '添加新书' : '编辑书籍')
.fontSize(22)
.margin(10);
TextInput({ text: this.book.bookName })
.placeholder('书名')
.onChange((value: string) => {
this.book.bookName = value;
})
.width('90%');
TextInput({ text: this.book.author })
.placeholder('作者')
.onChange((value: string) => {
this.book.author = value;
})
.width('90%');
TextInput({ text: this.book.price.toString() })
.placeholder('价格')
.type(InputType.Number)
.onChange((value: string) => {
this.book.price = parseFloat(value) || 0;
})
.width('90%');
Button(this.saving ? '保存中...' : '保存')
.width(200)
.height(50)
.backgroundColor(Color.Blue)
.enabled(!this.saving)
.onClick(() => {
this.saveBook();
})
}
.width('100%')
.height('100%')
.padding(20)
}
}
八、性能优化与调试技巧
-
批量操作优化
// 在CloudDBManager中添加
async batchAddBooks(books: BookInfo[]): Promise{
try {
const db = this.getCloudDB();// 分配ID books.forEach(book => { book.id = this.generateId(); book.lastReadTime = new Date().getTime(); }); // 分批处理(每批50条) const batchSize = 50; for (let i = 0; i < books.length; i += batchSize) { const batch = books.slice(i, i + batchSize); await db.executeUpsert(batch); console.log(`已批量添加 ${batch.length} 本书籍`); }} catch (error) {
console.error('批量添加失败:', error);
throw error;
}
} -
数据同步状态监控
// 在CloudDBManager中添加
async getSyncStatus(): Promise<{
pendingWrites: number,
lastSyncTime: number,
syncError?: string
}> {
try {
const db = this.getCloudDB();
const pendingWrites = await db.getPendingWrites();return { pendingWrites: pendingWrites.length, lastSyncTime: Date.now() // 实际应用中应记录真实时间 };} catch (error) {
return {
pendingWrites: 0,
lastSyncTime: 0,
syncError: error.message
};
}
} -
调试日志配置
// 在应用启动时设置
clouddb.setLogLevel(clouddb.CloudDBLogLevel.DEBUG);
// 监听数据库事件
clouddb.on('event', (event) => {
console.log('CloudDB事件:', event.type, event.data);
if (event.type === 'syncComplete') {
console.log('数据同步完成');
} else if (event.type === 'syncError') {
console.error('同步错误:', event.data);
}
});
总结
通过本文的学习,你已经掌握了在HarmonyOS 5应用中实现AGC云数据库离线同步的核心技术:
环境配置:正确初始化云数据库服务
数据建模:定义支持离线同步的数据结构
CRUD操作:实现离线优先的数据访问
同步策略:配置冲突解决和网络状态感知
实战案例:构建完整的离线优先应用
AGC云数据库的离线同步能力为HarmonyOS应用提供了:
无缝用户体验:网络中断不影响核心功能
数据一致性:自动解决多设备同步冲突
开发效率:简化本地和云端数据管理
在实际项目中,你还可以进一步探索:
更复杂的冲突解决策略
数据变更订阅通知
与AGC认证服务的深度集成
大数据量下的性能调优

浙公网安备 33010602011771号