鸿蒙跨端用户偏好同步:主题设置多设备实时同步方案 原创

进修的泡芙
发布于 2025-6-18 21:13
浏览
0收藏

鸿蒙跨端用户偏好同步:主题设置多设备实时同步方案

本文将基于HarmonyOS 5的Preferences数据存储和分布式能力,实现一个跨设备的主题偏好设置系统,能够在不同设备间实时同步用户的主题选择(深色/浅色模式)。

技术架构
本地存储层:使用Preferences持久化存储主题设置

业务逻辑层:处理主题切换逻辑和跨设备同步

分布式同步层:通过分布式数据管理实现多设备同步

UI响应层:实时响应主题变化更新界面

完整代码实现
主题类型定义

// model/ThemeTypes.ts
export enum ThemeType {
LIGHT = ‘light’,
DARK = ‘dark’,
SYSTEM = ‘system’
export const THEME_KEY = ‘user_theme_preference’;

export const SYNC_THEME_KEY = ‘sync_theme_preference’;

本地主题管理服务

// service/LocalThemeService.ts
import { preferences } from ‘@ohos.data.preferences’;
import { THEME_KEY, ThemeType } from ‘…/model/ThemeTypes’;

const PREFERENCES_NAME = ‘user_settings’;

export class LocalThemeService {
private pref: preferences.Preferences;

// 初始化Preferences
async initPreferences() {
try {
this.pref = await preferences.getPreferences(globalThis.context, PREFERENCES_NAME);
catch (err) {

  console.error('Failed to init preferences:', err);

}

// 获取当前主题
async getTheme(): Promise<ThemeType> {
try {
const theme = await this.pref.get(THEME_KEY, ThemeType.SYSTEM);
return theme as ThemeType;
catch (err) {

  return ThemeType.SYSTEM;

}

// 设置主题
async setTheme(theme: ThemeType): Promise<void> {
try {
await this.pref.put(THEME_KEY, theme);
await this.pref.flush();
catch (err) {

  console.error('Failed to save theme:', err);

}

分布式主题同步服务

// service/DistributedThemeService.ts
import distributedData from ‘@ohos.data.distributedData’;
import { SYNC_THEME_KEY, ThemeType } from ‘…/model/ThemeTypes’;

const STORE_ID = ‘theme_sync_store’;

export class DistributedThemeService {
private kvManager: distributedData.KVManager;
private kvStore: distributedData.SingleKVStore;

// 初始化分布式数据库
async initKVStore() {
const config = {
bundleName: ‘com.example.themeapp’,
userInfo: {
userId: ‘defaultUser’,
userType: distributedData.UserType.SAME_USER_ID
};

this.kvManager = distributedData.createKVManager(config);
const options = {
  createIfMissing: true,
  encrypt: false,
  backup: false,
  autoSync: true,
  kvStoreType: distributedData.KVStoreType.SINGLE_VERSION
};

this.kvStore = await this.kvManager.getKVStore(STORE_ID, options);

// 订阅主题变更
this.kvStore.on('dataChange', distributedData.SubscribeType.SUBSCRIBE_TYPE_ALL, (data) => {
  this.handleThemeChange(data);
});

// 处理主题变更

private handleThemeChange(data: distributedData.ChangeNotification) {
if (data.insertEntries.length > 0) {
const entry = data.insertEntries.find(e => e.key === SYNC_THEME_KEY);
if (entry) {
const newTheme = entry.value.value as ThemeType;
AppStorage.setOrCreate(‘currentTheme’, newTheme);

    // 更新本地存储
    const themeManager = new LocalThemeService();
    themeManager.setTheme(newTheme);
    themeManager.applyThemeToUI(newTheme);

}

// 同步主题到其他设备

async syncTheme(theme: ThemeType) {
try {
await this.kvStore.put(SYNC_THEME_KEY, theme);
catch (err) {

  console.error('Failed to sync theme:', err);

}

主题设置页面实现

// pages/ThemeSettingPage.ets
import { ThemeType } from ‘…/model/ThemeTypes’;
import { LocalThemeService } from ‘…/service/LocalThemeService’;
import { DistributedThemeService } from ‘…/service/DistributedThemeService’;

@Entry
@Component
struct ThemeSettingPage {
private localThemeService: LocalThemeService = new LocalThemeService();
private distThemeService: DistributedThemeService = new DistributedThemeService();
@State currentTheme: ThemeType = ThemeType.SYSTEM;
@State isSyncing: boolean = false;

async aboutToAppear() {
await this.localThemeService.initPreferences();
await this.distThemeService.initKVStore();
this.currentTheme = await this.localThemeService.getTheme();
build() {

Column() {
  Text('主题设置')
    .fontSize(24)
    .fontWeight(FontWeight.Bold)
    .margin({ top: 20, bottom: 30 })
  
  // 主题选项
  Column() {
    ThemeOption({
      theme: ThemeType.LIGHT,
      current: this.currentTheme,
      title: '浅色模式',
      icon: $r('app.media.ic_light'),
      onSelect: () => this.changeTheme(ThemeType.LIGHT)
    })
    
    Divider().margin(10)
    
    ThemeOption({
      theme: ThemeType.DARK,
      current: this.currentTheme,
      title: '深色模式',
      icon: $r('app.media.ic_dark'),
      onSelect: () => this.changeTheme(ThemeType.DARK)
    })
    
    Divider().margin(10)
    
    ThemeOption({
      theme: ThemeType.SYSTEM,
      current: this.currentTheme,
      title: '跟随系统',
      icon: $r('app.media.ic_system'),
      onSelect: () => this.changeTheme(ThemeType.SYSTEM)
    })

.width(‘90%’)

  .padding(20)
  .backgroundColor($r('app.color.card_background'))
  .borderRadius(12)
  
  // 同步开关
  Row() {
    Text('跨设备同步主题设置')
      .fontSize(16)
      .layoutWeight(1)
    
    Toggle({ type: ToggleType.Switch })
      .onChange((isOn: boolean) => {
        AppStorage.setOrCreate('syncThemeEnabled', isOn);
      })

.width(‘90%’)

  .margin({ top: 30 })
  
  // 同步状态
  if (this.isSyncing) {
    Row() {
      LoadingProgress()
        .width(20)
        .height(20)
        .margin({ right: 8 })
      Text('同步中...')
        .fontSize(14)
        .fontColor('#666666')

.margin({ top: 20 })

}

.width('100%')
.height('100%')
.backgroundColor($r('app.color.background'))

// 切换主题

private async changeTheme(theme: ThemeType) {
this.currentTheme = theme;
await this.localThemeService.setTheme(theme);
this.applyTheme(theme);

// 如果开启了同步,则同步到其他设备
if (AppStorage.get('syncThemeEnabled')) {
  this.isSyncing = true;
  await this.distThemeService.syncTheme(theme);
  this.isSyncing = false;

}

// 应用主题到UI
private applyTheme(theme: ThemeType) {
const systemUI = getContext().resourceManager;

if (theme === ThemeType.SYSTEM) {
  // 跟随系统主题
  const isDarkMode = systemUI.getConfiguration().colorMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK;
  theme = isDarkMode ? ThemeType.DARK : ThemeType.LIGHT;

// 更新全局主题变量

AppStorage.setOrCreate('currentTheme', theme);

// 实际应用中这里可以设置状态栏、导航栏等系统UI
if (theme === ThemeType.DARK) {
  systemUI.setDarkMode(true);

else {

  systemUI.setDarkMode(false);

}

@Component

struct ThemeOption {
@Prop theme: ThemeType;
@Prop current: ThemeType;
@Prop title: string;
@Prop icon: Resource;
@Prop onSelect: () => void;

build() {
Row() {
Image(this.icon)
.width(24)
.height(24)
.margin({ right: 15 })

  Text(this.title)
    .fontSize(18)
    .layoutWeight(1)
  
  if (this.theme === this.current) {
    Image($r('app.media.ic_check'))
      .width(20)
      .height(20)

}

.width('100%')
.height(60)
.onClick(() => {
  this.onSelect();
})

}

主题应用扩展

// 扩展CommonMethod支持主题样式
declare module ‘@ohos.arkui.base’ {
interface CommonMethod<T> {
themeStyles(theme: ThemeType): T;
}

CommonMethod.prototype.themeStyles = function<T>(this: CommonMethod<T>, theme: ThemeType): T {
const isDark = theme === ThemeType.DARK;
return this
.backgroundColor(isDark ? r(‘app.color.dark_background’) : r(‘app.color.light_background’))
.fontColor(isDark ? r(‘app.color.dark_text’) : r(‘app.color.light_text’));
};

// 在页面中使用
@Component
struct ThemedComponent {
@StorageLink(‘currentTheme’) currentTheme: ThemeType;

build() {
Column() {
Text(‘主题化组件’)
.themeStyles(this.currentTheme)
}

实现原理详解
数据存储与同步流程:

用户在一个设备上更改主题设置

设置首先保存到本地Preferences

如果开启了同步,通过分布式KVStore同步到其他设备

其他设备收到变更通知后更新本地Preferences和UI
主题应用机制:

使用AppStorage管理当前主题状态

通过自定义扩展方法统一应用主题样式

支持动态切换不重启应用
冲突解决策略:

最后修改的设备优先级最高

同步时携带时间戳解决冲突

本地变更优先于远程变更

扩展功能建议
主题同步历史记录:

  // 记录主题变更历史

async recordThemeChange(theme: ThemeType, deviceId: string) {
const historyKey = ‘theme_change_history’;
const history = await this.pref.get(historyKey, []);
history.push({
theme,
deviceId,
timestamp: new Date().toISOString()
});
await this.pref.put(historyKey, history.slice(-10)); // 保留最近10条记录

多主题扩展支持:

  // 支持自定义主题

enum CustomTheme {
BLUE = ‘blue’,
GREEN = ‘green’,
PINK = ‘pink’
// 动态加载主题资源

function getThemeResource(theme: string) {
switch (theme) {
case CustomTheme.BLUE:
return { bgColor: ‘#E3F2FD’, textColor: ‘#0D47A1’ };
// 其他主题…
}

同步冲突可视化:

  // 显示同步冲突解决界面

function showConflictResolution(localTheme: ThemeType, remoteTheme: ThemeType) {
AlertDialog.show({
title: ‘主题冲突’,
message: 本地主题: {localTheme}\n远程主题: {remoteTheme},
buttons: [
text: ‘使用本地’, action: () => this.syncTheme(localTheme) },

text: ‘使用远程’, action: () => this.applyTheme(remoteTheme) }

});

总结

本文展示了如何利用HarmonyOS的Preferences和分布式能力实现跨设备的主题偏好同步系统。通过本地存储确保单设备体验的一致性,再通过分布式数据管理扩展到多设备场景,为用户提供无缝的跨设备主题体验。

这种模式不仅适用于主题设置,还可以扩展到字体大小、语言偏好、通知设置等各种用户偏好设置场景,是构建HarmonyOS全场景应用的重要模式之一。合理利用这些能力,可以显著提升用户体验和应用粘性。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏
回复
举报
回复
    相关推荐