📊
鸿蒙应用开发:数据管理与可视化
一、章节概述
✅ 学习目标
💡 核心重点
数据管理的核心概念、数据可视化的实现方式、实战案例、常见问题与解决方案
⚠️ 前置基础
已完成第1-42章内容,具备鸿蒙应用开发的全流程技能,了解组件化开发、权限管理等
二、鸿蒙数据管理的核心概念
2.1 本地存储
2.1.1 本地存储方式
- Preferences:轻量级存储方式,适用于存储应用配置数据
- SQLite数据库:关系型数据库,适用于存储结构化数据
- 文件存储:用于存储非结构化数据,如图片、音频、视频等
2.1.2 Preferences实战案例
// entry/src/main/ets/utils/preferences.ets Preferences工具
import dataPreferences from '@ohos.data.preferences';
import common from '@ohos.app.ability.common';
export async function getPreference(context: common.UIAbilityContext, key: string, defaultValue: any): Promise<any> {
try {
const preference = await dataPreferences.getPreferences(context, 'app_preferences');
return await preference.get(key, defaultValue);
} catch (err) {
console.error(`获取偏好设置失败: ${JSON.stringify(err)}`);
return defaultValue;
}
}
export async function setPreference(context: common.UIAbilityContext, key: string, value: any): Promise<boolean> {
try {
const preference = await dataPreferences.getPreferences(context, 'app_preferences');
await preference.put(key, value);
await preference.flush();
return true;
} catch (err) {
console.error(`设置偏好设置失败: ${JSON.stringify(err)}`);
return false;
}
}
export async function removePreference(context: common.UIAbilityContext, key: string): Promise<boolean> {
try {
const preference = await dataPreferences.getPreferences(context, 'app_preferences');
await preference.delete(key);
await preference.flush();
return true;
} catch (err) {
console.error(`删除偏好设置失败: ${JSON.stringify(err)}`);
return false;
}
}
// entry/src/main/ets/pages/PreferencesPage.ets Preferences页面
import common from '@ohos.app.ability.common';
import { getPreference, setPreference, removePreference } from '../utils/preferences.ets';
@Entry
@Component
struct PreferencesPage {
@State context: common.UIAbilityContext | null = null;
@State username: string = '';
@State theme: string = 'light';
aboutToAppear() {
const ability = getCurrentAbility();
this.context = ability.context;
this.loadPreferences();
}
private async loadPreferences() {
if (!this.context) return;
this.username = await getPreference(this.context, 'username', '');
this.theme = await getPreference(this.context, 'theme', 'light');
}
private async savePreferences() {
if (!this.context) return;
const successUsername = await setPreference(this.context, 'username', this.username);
const successTheme = await setPreference(this.context, 'theme', this.theme);
if (successUsername && successTheme) {
promptAction.showToast({ message: '偏好设置已保存', duration: 2000 });
} else {
promptAction.showToast({ message: '偏好设置保存失败', duration: 2000 });
}
}
private async clearPreferences() {
if (!this.context) return;
const successUsername = await removePreference(this.context, 'username');
const successTheme = await removePreference(this.context, 'theme');
if (successUsername && successTheme) {
this.username = '';
this.theme = 'light';
promptAction.showToast({ message: '偏好设置已清除', duration: 2000 });
} else {
promptAction.showToast({ message: '偏好设置清除失败', duration: 2000 });
}
}
build() {
Column({ space: 16 }) {
Text('偏好设置')
.fontSize(28)
.fontWeight(FontWeight.Bold)
.fontColor(Color.Black);
TextInput({
text: this.username,
placeholder: '请输入用户名'
})
.width('100%')
.height(48)
.backgroundColor(Color.White)
.borderRadius(8)
.padding({ left: 12, right: 12 })
.onChange((value) => {
this.username = value;
});
Text('主题设置')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor(Color.Black);
Row({ space: 12 }) {
Radio({ value: 'light', group: 'theme' })
.checked(this.theme === 'light')
.onChange((value) => {
this.theme = value;
});
Text('浅色主题')
.fontSize(16)
.fontColor(Color.Black);
Radio({ value: 'dark', group: 'theme' })
.checked(this.theme === 'dark')
.onChange((value) => {
this.theme = value;
});
Text('深色主题')
.fontSize(16)
.fontColor(Color.Black);
}
.width('100%');
Button('保存')
.width('100%')
.height(48)
.backgroundColor(Color.Green)
.fontColor(Color.White)
.onClick(() => {
this.savePreferences();
});
Button('清除')
.width('100%')
.height(48)
.backgroundColor(Color.Red)
.fontColor(Color.White)
.onClick(() => {
this.clearPreferences();
});
}
.padding(24)
.backgroundColor(Color.White);
}
}
三、鸿蒙数据可视化的实现方式
3.1 图表组件
3.1.1 图表组件概述
- Chart组件:鸿蒙提供的图表组件,支持折线图、柱状图、饼图等
- Chart属性:包括数据源、样式、交互等属性
- Chart事件:包括点击、滑动、缩放等事件
3.1.2 柱状图实战案例
// entry/src/main/ets/pages/BarChartPage.ets 柱状图页面
import chart from '@ohos.chart';
@Entry
@Component
struct BarChartPage {
@State data: Array<number> = [120, 200, 150, 180, 90, 140, 220];
@State labels: Array<string> = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
build() {
Column({ space: 16 }) {
Text('柱状图')
.fontSize(28)
.fontWeight(FontWeight.Bold)
.fontColor(Color.Black);
chart.BarChart({
data: this.data,
labels: this.labels,
xAxis: {
title: '日期',
fontSize: 14
},
yAxis: {
title: '销售额',
fontSize: 14
},
color: '#3B82F6'
})
.width('100%')
.height(300)
.backgroundColor(Color.White)
.borderRadius(8)
.onClick((index) => {
promptAction.showToast({
message: `${this.labels[index]}: ${this.data[index]}`,
duration: 2000
});
});
Row({ space: 12 }) {
Button('增加数据')
.width('50%')
.height(48)
.backgroundColor(Color.Blue)
.fontColor(Color.White)
.onClick(() => {
this.data.push(Math.floor(Math.random() * 200) + 100);
this.labels.push(`周${this.labels.length + 1}`);
});
Button('重置数据')
.width('50%')
.height(48)
.backgroundColor(Color.Red)
.fontColor(Color.White)
.onClick(() => {
this.data = [120, 200, 150, 180, 90, 140, 220];
this.labels = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
});
}
.width('100%');
}
.padding(24)
.backgroundColor(Color.White);
}
}
四、鸿蒙数据管理的实战案例
4.1 本地存储与网络请求结合
4.1.1 项目背景
- 需求:开发一个任务管理应用,支持本地存储与网络同步
- 功能:任务管理、本地存储、网络同步、数据可视化
- 技术:方舟开发框架、Preferences、SQLite、网络请求API
4.1.2 项目实现
// entry/src/main/ets/utils/taskManager.ets 任务管理工具
import dataPreferences from '@ohos.data.preferences';
import common from '@ohos.app.ability.common';
import { fetchData, postData } from '../utils/api.ets';
export interface Task {
id: string;
title: string;
description: string;
completed: boolean;
createdAt: number;
updatedAt: number;
}
export async function getTasks(context: common.UIAbilityContext): Promise<Array<Task>> {
try {
const remoteTasks = await fetchTasksFromRemote();
const localTasks = await getTasksFromLocal(context);
const mergedTasks = mergeTasks(localTasks, remoteTasks);
await saveTasksToLocal(context, mergedTasks);
return mergedTasks;
} catch (err) {
console.error(`获取任务失败: ${JSON.stringify(err)}`);
return await getTasksFromLocal(context);
}
}
export async function addTask(context: common.UIAbilityContext, task: Omit<Task, 'id' | 'createdAt' | 'updatedAt'>): Promise<Task> {
const newTask: Task = {
…task,
id: Date.now().toString(),
createdAt: Date.now(),
updatedAt: Date.now()
};
try {
await addTaskToRemote(newTask);
} catch (err) {
console.error(`添加远程任务失败: ${JSON.stringify(err)}`);
}
await addTaskToLocal(context, newTask);
return newTask;
}
export async function updateTask(context: common.UIAbilityContext, task: Task): Promise<boolean> {
const updatedTask = { …task, updatedAt: Date.now() };
try {
await updateTaskToRemote(updatedTask);
} catch (err) {
console.error(`更新远程任务失败: ${JSON.stringify(err)}`);
}
return await updateTaskToLocal(context, updatedTask);
}
export async function deleteTask(context: common.UIAbilityContext, id: string): Promise<boolean> {
try {
await deleteTaskFromRemote(id);
} catch (err) {
console.error(`删除远程任务失败: ${JSON.stringify(err)}`);
}
return await deleteTaskFromLocal(context, id);
}
// 本地存储方法
export async function getTasksFromLocal(context: common.UIAbilityContext): Promise<Array<Task>> {
try {
const preferences = await dataPreferences.getPreferences(context, 'task_preferences');
const tasksStr = await preferences.get('tasks', '[]');
return JSON.parse(tasksStr);
} catch (err) {
console.error(`获取本地任务失败: ${JSON.stringify(err)}`);
return [];
}
}
export async function saveTasksToLocal(context: common.UIAbilityContext, tasks: Array<Task>): Promise<boolean> {
try {
const preferences = await dataPreferences.getPreferences(context, 'task_preferences');
await preferences.put('tasks', JSON.stringify(tasks));
await preferences.flush();
return true;
} catch (err) {
console.error(`保存本地任务失败: ${JSON.stringify(err)}`);
return false;
}
}
export async function addTaskToLocal(context: common.UIAbilityContext, task: Task): Promise<boolean> {
const tasks = await getTasksFromLocal(context);
tasks.push(task);
return await saveTasksToLocal(context, tasks);
}
export async function updateTaskToLocal(context: common.UIAbilityContext, task: Task): Promise<boolean> {
const tasks = await getTasksFromLocal(context);
const index = tasks.findIndex(t => t.id === task.id);
if (index !== -1) {
tasks[index] = task;
return await saveTasksToLocal(context, tasks);
}
return false;
}
export async function deleteTaskFromLocal(context: common.UIAbilityContext, id: string): Promise<boolean> {
const tasks = await getTasksFromLocal(context);
const filteredTasks = tasks.filter(t => t.id !== id);
return await saveTasksToLocal(context, filteredTasks);
}
// 远程通信方法
export async function fetchTasksFromRemote(): Promise<Array<Task>> {
try {
const response = await fetchData('https://api.example.com/tasks');
return response.tasks;
} catch (err) {
console.error(`获取远程任务失败: ${JSON.stringify(err)}`);
return [];
}
}
export async function addTaskToRemote(task: Task): Promise<boolean> {
try {
const response = await postData('https://api.example.com/tasks', task);
return response.success;
} catch (err) {
console.error(`添加远程任务失败: ${JSON.stringify(err)}`);
return false;
}
}
export async function updateTaskToRemote(task: Task): Promise<boolean> {
try {
const response = await postData(`https://api.example.com/tasks/${task.id}`, task, 'PUT');
return response.success;
} catch (err) {
console.error(`更新远程任务失败: ${JSON.stringify(err)}`);
return false;
}
}
export async function deleteTaskFromRemote(id: string): Promise<boolean> {
try {
const response = await postData(`https://api.example.com/tasks/${id}`, {}, 'DELETE');
return response.success;
} catch (err) {
console.error(`删除远程任务失败: ${JSON.stringify(err)}`);
return false;
}
}
// 任务合并方法
function mergeTasks(localTasks: Array<Task>, remoteTasks: Array<Task>): Array<Task> {
const taskMap = new Map<string, Task>();
localTasks.forEach(task => taskMap.set(task.id, task));
remoteTasks.forEach(task => {
const existingTask = taskMap.get(task.id);
if (existingTask) {
// 如果远程任务更新时间晚于本地任务,则更新本地任务
if (task.updatedAt > existingTask.updatedAt) {
taskMap.set(task.id, task);
}
} else {
taskMap.set(task.id, task);
}
});
return Array.from(taskMap.values());
}
五、鸿蒙数据可视化的实战案例
5.1 任务管理应用数据可视化
5.1.1 项目背景
- 需求:在任务管理应用中添加数据可视化功能,展示任务完成情况
- 功能:任务完成率图表、任务分类图表、任务趋势图表
- 技术:方舟开发框架、Chart组件、任务管理工具
5.1.2 项目实现
// entry/src/main/ets/pages/TaskVisualizationPage.ets 任务可视化页面
import common from '@ohos.app.ability.common';
import chart from '@ohos.chart';
import { getTasks } from '../utils/taskManager.ets';
@Entry
@Component
struct TaskVisualizationPage {
@State context: common.UIAbilityContext | null = null;
@State tasks: Array<any> = [];
@State completedTasks: number = 0;
@State pendingTasks: number = 0;
@State taskCategories: Array<{ name: string; count: number }> = [
{ name: '工作', count: 0 },
{ name: '生活', count: 0 },
{ name: '学习', count: 0 },
{ name: '其他', count: 0 }
];
aboutToAppear() {
const ability = getCurrentAbility();
this.context = ability.context;
this.loadTasks();
}
private async loadTasks() {
if (!this.context) return;
const tasks = await getTasks(this.context);
this.tasks = tasks;
this.completedTasks = tasks.filter(task => task.completed).length;
this.pendingTasks = tasks.filter(task => !task.completed).length;
this.calculateTaskCategories(tasks);
}
private calculateTaskCategories(tasks: Array<any>) {
const categoryMap = new Map<string, number>();
tasks.forEach(task => {
const category = task.category || '其他';
categoryMap.set(category, (categoryMap.get(category) || 0) + 1);
});
this.taskCategories = Array.from(categoryMap.entries()).map(([name, count]) => ({
name,
count
}));
}
build() {
Column({ space: 16 }) {
Text('任务可视化')
.fontSize(28)
.fontWeight(FontWeight.Bold)
.fontColor(Color.Black);
// 任务完成率图表
Text('任务完成率')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor(Color.Black);
chart.PieChart({
data: [this.completedTasks, this.pendingTasks],
labels: ['已完成', '待完成'],
colors: ['#10B981', '#EF4444']
})
.width('100%')
.height(200)
.backgroundColor(Color.White)
.borderRadius(8);
// 任务分类图表
Text('任务分类')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor(Color.Black);
chart.BarChart({
data: this.taskCategories.map(category => category.count),
labels: this.taskCategories.map(category => category.name),
xAxis: {
title: '分类',
fontSize: 14
},
yAxis: {
title: '数量',
fontSize: 14
},
color: '#3B82F6'
})
.width('100%')
.height(200)
.backgroundColor(Color.White)
.borderRadius(8);
// 任务列表
Text('任务列表')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor(Color.Black);
List({ space: 12 }) {
LazyForEach(new TaskDataSource(this.tasks), (item: any) => {
ListItem() {
Row({ space: 12 }) {
Checkbox()
.width(24)
.height(24)
.checked(item.completed)
.onChange((checked) => {
this.updateTask(item.id, checked);
});
Column({ space: 4 }) {
Text(item.title)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor(Color.Black);
Text(item.description)
.fontSize(14)
.fontColor(Color.Gray);
}
.layoutWeight(1);
Text(item.completed ? '已完成' : '待完成')
.fontSize(14)
.fontColor(item.completed ? Color.Green : Color.Red);
}
.width('100%')
.height(60)
.padding({ left: 12, right: 12 })
.backgroundColor(Color.White)
.borderRadius(8)
.shadow({ offsetX: 0, offsetY: 2, radius: 4, color: '#00000014' });
}
});
}
.width('100%')
.height('100%')
.layoutWeight(1);
}
.padding(24)
.backgroundColor(Color.White);
}
private async updateTask(id: string, completed: boolean) {
if (!this.context) return;
const task = this.tasks.find(task => task.id === id);
if (task) {
task.completed = completed;
// await updateTask(this.context, task);
this.completedTasks = this.tasks.filter(task => task.completed).length;
this.pendingTasks = this.tasks.filter(task => !task.completed).length;
promptAction.showToast({
message: '任务状态已更新',
duration: 2000
});
}
}
}
class TaskDataSource implements IDataSource {
private tasks: Array<any> = [];
constructor(tasks: Array<any>) {
this.tasks = tasks;
}
totalCount(): number {
return this.tasks.length;
}
getData(index: number): any {
return this.tasks[index];
}
notifyDataChanged(): void {
// 数据更新时调用
}
notifyDataAdd(index: number): void {
// 数据添加时调用
}
notifyDataChange(index: number): void {
// 数据修改时调用
}
notifyDataDelete(index: number): void {
// 数据删除时调用
}
}
六、鸿蒙数据管理与可视化的常见问题与解决方案
6.1 本地存储与网络同步问题
- 问题:本地存储与网络同步时数据不一致
- 解决方案:
- 使用时间戳机制,确保数据更新的先后顺序
- 实现数据合并策略,优先保留更新时间较晚的数据
- 提供数据同步状态提示,确保用户知道数据同步情况
6.2 图表性能问题
- 问题:图表数据量过大导致界面卡顿
- 解决方案:
- 对数据进行采样或分页处理,减少图表数据量
- 使用缓存机制,避免重复计算数据
- 优化图表渲染逻辑,提升渲染效率
6.3 数据处理问题
- 问题:数据处理逻辑复杂导致应用响应慢
- 解决方案:
- 使用异步数据处理,避免阻塞界面
- 对数据处理逻辑进行优化,提升处理效率
- 使用多线程或并发处理,提高数据处理速度
七、总结与建议
7.1 核心总结
鸿蒙数据管理与可视化是鸿蒙应用开发的核心内容,通过本地存储、网络请求、数据同步、图表展示等技术,实现了应用的数据管理与可视化功能。
7.2 建议
通过不断优化与创新,开发者可以构建出数据管理与可视化功能完善的鸿蒙应用,从而提升应用的竞争力与用户满意度。📊
网硕互联帮助中心



评论前必须登录!
注册