鸿蒙跨设备待办事项应用设计与实现 原创

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

鸿蒙跨设备待办事项应用设计与实现

一、系统架构设计

基于HarmonyOS的分布式能力,我们设计了一个跨设备同步的简易待办事项应用,使用数组存储任务列表并实现多设备同步。

!https://example.com/todo-app-arch.png

系统包含三个核心模块:
数据存储模块 - 使用数组存储任务列表

分布式同步模块 - 通过@ohos.distributedData实现多设备同步

UI组件模块 - 提供任务列表展示和操作界面

二、核心代码实现
任务数据模型与服务(ArkTS)

// TaskService.ets
import distributedData from ‘@ohos.distributedData’;

const TODO_SYNC_CHANNEL = ‘todo_sync_channel’;

interface Task {
id: string;
title: string;
completed: boolean;
createdAt: number;
updatedAt: number;
class TaskService {

private static instance: TaskService = null;
private dataManager: distributedData.DataManager;
private tasks: Task[] = [];
private listeners: TaskListener[] = [];

private constructor() {
this.initDataManager();
this.loadInitialData();
public static getInstance(): TaskService {

if (!TaskService.instance) {
  TaskService.instance = new TaskService();

return TaskService.instance;

private initDataManager() {

this.dataManager = distributedData.createDataManager({
  bundleName: 'com.example.tododemo',
  area: distributedData.Area.GLOBAL
});

this.dataManager.registerDataListener(TODO_SYNC_CHANNEL, (data) => {
  this.handleSyncData(data);
});

private loadInitialData() {

// 初始示例数据
this.tasks = [

id: ‘1’, title: ‘学习ArkTS’, completed: false, createdAt: Date.now(), updatedAt: Date.now() },

id: ‘2’, title: ‘开发待办事项应用’, completed: false, createdAt: Date.now(), updatedAt: Date.now() }

];

public getAllTasks(): Task[] {

return [...this.tasks];

public getActiveTasks(): Task[] {

return this.tasks.filter(task => !task.completed);

public getCompletedTasks(): Task[] {

return this.tasks.filter(task => task.completed);

public addTask(title: string): void {

const newTask: Task = {
  id: Date.now().toString(),
  title: title,
  completed: false,
  createdAt: Date.now(),
  updatedAt: Date.now()
};

this.tasks = [...this.tasks, newTask];
this.notifyListeners();
this.syncTasks();

public toggleTask(id: string): void {

this.tasks = this.tasks.map(task => {
  if (task.id === id) {
    return {
      ...task,
      completed: !task.completed,
      updatedAt: Date.now()
    };

return task;

});

this.notifyListeners();
this.syncTasks();

public deleteTask(id: string): void {

this.tasks = this.tasks.filter(task => task.id !== id);
this.notifyListeners();
this.syncTasks();

public clearCompleted(): void {

this.tasks = this.tasks.filter(task => !task.completed);
this.notifyListeners();
this.syncTasks();

public addListener(listener: TaskListener): void {

if (!this.listeners.includes(listener)) {
  this.listeners.push(listener);

}

public removeListener(listener: TaskListener): void {
this.listeners = this.listeners.filter(l => l !== listener);
private notifyListeners(): void {

this.listeners.forEach(listener => {
  listener.onTasksChanged(this.getAllTasks());
});

private syncTasks(): void {

this.dataManager.syncData(TODO_SYNC_CHANNEL, {
  type: 'fullSync',
  tasks: this.tasks
});

private handleSyncData(data: any): void {

if (data?.type === 'fullSync' && data.tasks) {
  // 简单的冲突解决策略:保留最新更新的任务
  const remoteTasks: Task[] = data.tasks;
  const mergedTasks: Task[] = [];
  
  // 合并本地和远程任务
  const allTasks = [...this.tasks, ...remoteTasks];
  const taskMap = new Map<string, Task>();
  
  allTasks.forEach(task => {
    if (!taskMap.has(task.id) |

(taskMap.get(task.id)?.updatedAt
| 0) < task.updatedAt) {
taskMap.set(task.id, task);
});

  this.tasks = Array.from(taskMap.values());
  this.notifyListeners();

}

interface TaskListener {

onTasksChanged(tasks: Task[]): void;
export const taskService = TaskService.getInstance();

待办事项主界面(ArkUI)

// TodoApp.ets
import { taskService } from ‘./TaskService’;

@Entry
@Component
struct TodoApp {
@State tasks: Task[] = [];
@State newTaskTitle: string = ‘’;
@State filter: ‘all’ ‘active’
‘completed’ = ‘all’;

private taskListener: TaskListener = {
onTasksChanged: (tasks) => {
this.tasks = tasks;
};

aboutToAppear() {
taskService.addListener(this.taskListener);
this.tasks = taskService.getAllTasks();
aboutToDisappear() {

taskService.removeListener(this.taskListener);

build() {

Column() {
  // 标题
  Text('待办事项')
    .fontSize(24)
    .fontWeight(FontWeight.Bold)
    .margin({ bottom: 20 })
  
  // 新增任务输入框
  Row() {
    TextInput({ placeholder: '输入新任务', text: this.newTaskTitle })
      .onChange((value: string) => {
        this.newTaskTitle = value;
      })
      .onSubmit(() => {
        this.addTask();
      })
      .layoutWeight(1)
    
    Button('添加')
      .onClick(() => {
        this.addTask();
      })

.margin({ bottom: 20 })

  // 过滤选项
  Row() {
    Button('全部')
      .stateEffect(!(this.filter === 'all'))
      .onClick(() => {
        this.filter = 'all';
      })
    
    Button('未完成')
      .margin({ left: 10 })
      .stateEffect(!(this.filter === 'active'))
      .onClick(() => {
        this.filter = 'active';
      })
    
    Button('已完成')
      .margin({ left: 10 })
      .stateEffect(!(this.filter === 'completed'))
      .onClick(() => {
        this.filter = 'completed';
      })

.margin({ bottom: 20 })

  // 任务列表
  List({ space: 10 }) {
    ForEach(this.getFilteredTasks(), (task) => {
      ListItem() {
        this.buildTaskItem(task);

})

.layoutWeight(1)

  // 底部操作栏
  Row() {
    Text(${this.getActiveTasksCount()} 项未完成)
    
    Button('清除已完成')
      .margin({ left: 20 })
      .onClick(() => {
        taskService.clearCompleted();
      })

.margin({ top: 20 })

.padding(20)

.height('100%')

@Builder

buildTaskItem(task: Task) {
Row() {
// 完成状态切换
Checkbox()
.select(task.completed)
.onChange((checked: boolean) => {
taskService.toggleTask(task.id);
})

  // 任务标题
  Text(task.title)
    .fontSize(18)
    .textDecoration(task.completed ? TextDecoration.LineThrough : TextDecoration.None)
    .opacity(task.completed ? 0.6 : 1)
    .margin({ left: 10 })
    .layoutWeight(1)
  
  // 删除按钮
  Button('删除')
    .onClick(() => {
      taskService.deleteTask(task.id);
    })

.width(‘100%’)

.padding(10)
.backgroundColor('#FFFFFF')
.borderRadius(8)

private addTask() {

if (this.newTaskTitle.trim()) {
  taskService.addTask(this.newTaskTitle.trim());
  this.newTaskTitle = '';

}

private getFilteredTasks(): Task[] {
switch (this.filter) {
case ‘active’:
return taskService.getActiveTasks();
case ‘completed’:
return taskService.getCompletedTasks();
default:
return taskService.getAllTasks();
}

private getActiveTasksCount(): number {
return taskService.getActiveTasks().length;
}

跨设备同步增强实现

// EnhancedTodoSync.ets
import deviceManager from ‘@ohos.distributedDeviceManager’;

class EnhancedTodoSync {
private deviceManager: deviceManager.DeviceManager;
private lastSyncTime: number = 0;

constructor() {
this.initDeviceManager();
private async initDeviceManager() {

try {
  this.deviceManager = await deviceManager.createDeviceManager('com.example.tododemo');
  this.deviceManager.on('deviceOnline', (device) => {
    this.syncWithDevice(device.deviceId);
  });

catch (err) {

  console.error('初始化DeviceManager失败:', JSON.stringify(err));

}

public async fullSync() {
const devices = this.deviceManager.getTrustedDeviceListSync();
devices.forEach(device => {
this.syncWithDevice(device.deviceId);
});
private async syncWithDevice(deviceId: string) {

const tasks = taskService.getAllTasks();
const syncData = {
  type: 'incrementalSync',
  tasks: tasks,
  timestamp: Date.now(),
  deviceId: this.getLocalDeviceId()
};

distributedData.syncData(TODO_SYNC_CHANNEL, syncData, {
  targetDevice: deviceId
});

private getLocalDeviceId(): string {

// 实际实现需要获取设备ID
return 'local_device';

public handleIncomingSync(data: any) {

if (data?.type === 'incrementalSync' && data.tasks) {
  const remoteTasks: Task[] = data.tasks;
  const remoteTimestamp = data.timestamp || 0;
  
  // 简单的冲突解决:如果远程数据更新,则使用远程数据
  if (remoteTimestamp > this.lastSyncTime) {
    taskService.syncTasks(remoteTasks);
    this.lastSyncTime = remoteTimestamp;

}

}

export const enhancedTodoSync = new EnhancedTodoSync();

三、权限配置与模块声明
配置文件

// module.json5
“module”: {

"requestPermissions": [

“name”: “ohos.permission.DISTRIBUTED_DATASYNC”,

    "reason": "跨设备同步待办事项"

],

"abilities": [

“name”: “MainAbility”,

    "type": "page",
    "visible": true

],

"distributedNotification": {
  "scenarios": [

“name”: “todo_sync”,

      "value": "todo_list"

]

}

资源文件

<!-- resources/base/element/string.json -->
“string”: [

“name”: “app_name”,

  "value": "待办事项"
},

“name”: “new_task_hint”,

  "value": "输入新任务"
},

“name”: “add_button”,

  "value": "添加"
},

“name”: “all_filter”,

  "value": "全部"
},

“name”: “active_filter”,

  "value": "未完成"
},

“name”: “completed_filter”,

  "value": "已完成"
},

“name”: “items_left”,

  "value": "项未完成"
},

“name”: “clear_completed”,

  "value": "清除已完成"

]

四、数组操作示例
基本数组操作

// 创建数组
let tasks: Task[] = [];

// 添加元素
tasks.push({ id: ‘1’, title: ‘任务1’, completed: false });
tasks = […tasks, { id: ‘2’, title: ‘任务2’, completed: false }];

// 删除元素
tasks = tasks.filter(task => task.id !== ‘1’);

// 更新元素
tasks = tasks.map(task =>
task.id === ‘2’ ? { …task, completed: true } : task
);

// 查找元素
const task = tasks.find(task => task.id === ‘2’);

// 排序
tasks.sort((a, b) => a.title.localeCompare(b.title));

// 过滤
const completedTasks = tasks.filter(task => task.completed);

复杂数组操作

// 分组
const groupedTasks = tasks.reduce((acc, task) => {
const key = task.completed ? ‘completed’ : ‘active’;
if (!acc[key]) {
acc[key] = [];
acc[key].push(task);

return acc;
}, {});

// 批量更新
const updatedTasks = tasks.map(task => ({
…task,
updatedAt: Date.now()
}));

// 批量删除
const idsToDelete = [‘1’, ‘2’];
tasks = tasks.filter(task => !idsToDelete.includes(task.id));

// 数组去重
const uniqueTasks = tasks.filter(
(task, index, self) => index = self.findIndex(t => t.id = task.id)
);

五、项目扩展方向
增加任务分类

interface Category {
id: string;
name: string;
color: string;
interface Task {

// …其他字段
categoryId?: string;
// 按分类过滤任务

function getTasksByCategory(tasks: Task[], categoryId: string): Task[] {
return tasks.filter(task => task.categoryId === categoryId);

增加任务优先级

enum Priority {
LOW = ‘low’,
MEDIUM = ‘medium’,
HIGH = ‘high’
interface Task {

// …其他字段
priority: Priority;
// 按优先级排序

tasks.sort((a, b) => {
const priorityOrder = [Priority.HIGH, Priority.MEDIUM, Priority.LOW];
return priorityOrder.indexOf(a.priority) - priorityOrder.indexOf(b.priority);
});

增加任务提醒

import notification from ‘@ohos.notification’;

interface Task {
// …其他字段
reminderTime?: number;
function scheduleReminder(task: Task) {

if (task.reminderTime) {
const delay = task.reminderTime - Date.now();
if (delay > 0) {
setTimeout(() => {
notification.publish({
content: {
title: ‘任务提醒’,
text: task.title
});

  }, delay);

}

增加任务历史记录

interface TaskHistory {
taskId: string;
action: ‘create’ ‘update’
‘delete’;
timestamp: number;
data?: Task;
function logTaskAction(task: Task, action: ‘create’ ‘update’
‘delete’) {

const history: TaskHistory = {
taskId: task.id,
action,
timestamp: Date.now(),
data: action !== ‘delete’ ? task : undefined
};

// 存储历史记录
// …

六、总结

通过这个简易待办事项应用的实现,我们学习了:
使用数组存储和管理任务数据

实现基本的CRUD操作(创建、读取、更新、删除)

利用HarmonyOS的分布式能力实现跨设备同步

构建响应式的用户界面

处理数据同步冲突

这个应用可以进一步扩展为功能更完善的任务管理工具,如添加任务分类、优先级、提醒功能等。同时,分布式同步能力可以确保用户在不同设备上都能访问到最新的任务列表。

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