第9次课
课前回顾
1.数据持久化,比如在备忘录应用中,当用户添加、删除、修改了数据时,数据需要持久化到本地。
2.preference的使用,比如在备忘录应用中,用户设置主题色时,需要保存到本地。
在鸿蒙(HarmonyOS)应用开发中,Preference首选项是一种轻量级的数据持久化存储方案,主要用于存储少量、简单的键值对数据。以下是关于Preference首选项的详细阐述:
1. Preference首选项概述
Preference是一种基于键值对(Key-Value)的轻量级存储机制,适用于保存应用的配置信息、用户设置等小规模数据。
特点:
- 数据以XML文件形式存储
- 线程安全,支持异步操作
- 存储简单数据类型
- 自动持久化到设备存储
2. 基本使用方法
2.1 获取Preference实例
import preferences from '@ohos.data.preferences';
// 获取Preference实例
let preferences: Promise<preferences.Preferences> = preferences.getPreferences(this.context, 'myAppPrefs');
2.2 存储数据
async function saveData() {
try {
let pref = await preferences.getPreferences(this.context, 'myAppPrefs');
// 存储不同类型的数据
await pref.put('username', '张三');
await pref.put('age', 25);
await pref.put('isLoggedIn', true);
await pref.put('score', 95.5);
// 提交保存
await pref.flush();
console.log('数据保存成功');
} catch (err) {
console.error('保存数据失败: ' + err);
}
}
2.3 读取数据
async function readData() {
try {
let pref = await preferences.getPreferences(this.context, 'myAppPrefs');
// 读取数据,第二个参数为默认值
let username = await pref.get('username', '默认用户');
let age = await pref.get('age', 0);
let isLoggedIn = await pref.get('isLoggedIn', false);
let score = await pref.get('score', 0.0);
console.log(`用户名: ${username}`);
console.log(`年龄: ${age}`);
console.log(`登录状态: ${isLoggedIn}`);
console.log(`分数: ${score}`);
} catch (err) {
console.error('读取数据失败: ' + err);
}
}
3. 完整示例代码
import preferences from '@ohos.data.preferences';
export default class PreferenceUtils {
private static PREF_NAME = 'myAppPreferences';
// 保存用户信息
static async saveUserInfo(userInfo: UserInfo) {
try {
let pref = await preferences.getPreferences(getContext(), this.PREF_NAME);
await pref.put('userId', userInfo.id);
await pref.put('userName', userInfo.name);
await pref.put('userEmail', userInfo.email);
await pref.put('loginTime', Date.now());
await pref.put('rememberMe', userInfo.rememberMe);
await pref.flush();
console.log('用户信息保存成功');
} catch (err) {
console.error('保存用户信息失败: ' + err);
}
}
// 读取用户信息
static async getUserInfo(): Promise<UserInfo> {
try {
let pref = await preferences.getPreferences(getContext(), this.PREF_NAME);
return {
id: await pref.get('userId', ''),
name: await pref.get('userName', ''),
email: await pref.get('userEmail', ''),
loginTime: await pref.get('loginTime', 0),
rememberMe: await pref.get('rememberMe', false)
};
} catch (err) {
console.error('读取用户信息失败: ' + err);
return new UserInfo();
}
}
// 删除指定数据
static async deleteKey(key: string) {
try {
let pref = await preferences.getPreferences(getContext(), this.PREF_NAME);
await pref.delete(key);
await pref.flush();
} catch (err) {
console.error('删除数据失败: ' + err);
}
}
// 清空所有数据
static async clearAll() {
try {
let pref = await preferences.getPreferences(getContext(), this.PREF_NAME);
await pref.clear();
await pref.flush();
} catch (err) {
console.error('清空数据失败: ' + err);
}
}
}
class UserInfo {
id: string = '';
name: string = '';
email: string = '';
loginTime: number = 0;
rememberMe: boolean = false;
}
4. 高级用法
4.1 数据变更监听
async function setupPreferenceListener() {
try {
let pref = await preferences.getPreferences(this.context, 'myAppPrefs');
// 添加数据变更监听器
pref.on('change', (key: string) => {
console.log(`数据发生变化: ${key}`);
// 执行相应的业务逻辑
});
} catch (err) {
console.error('设置监听器失败: ' + err);
}
}
4.2 多Preference文件管理
class MultiPreferenceManager {
private static USER_PREF = 'user_preferences';
private static APP_PREF = 'app_preferences';
private static CACHE_PREF = 'cache_preferences';
// 获取不同的Preference文件
static async getUserPreferences() {
return await preferences.getPreferences(getContext(), this.USER_PREF);
}
static async getAppPreferences() {
return await preferences.getPreferences(getContext(), this.APP_PREF);
}
static async getCachePreferences() {
return await preferences.getPreferences(getContext(), this.CACHE_PREF);
}
}
5. 最佳实践
5.1 封装工具类
export class PreferenceHelper {
private prefName: string;
constructor(prefName: string) {
this.prefName = prefName;
}
// 安全地保存数据
async safePut(key: string, value: preferences.ValueType): Promise<boolean> {
try {
let pref = await preferences.getPreferences(getContext(), this.prefName);
await pref.put(key, value);
await pref.flush();
return true;
} catch (err) {
console.error(`保存数据失败 key:${key}`, err);
return false;
}
}
// 安全地读取数据
async safeGet<T extends preferences.ValueType>(key: string, defaultValue: T): Promise<T> {
try {
let pref = await preferences.getPreferences(getContext(), this.prefName);
return await pref.get(key, defaultValue) as T;
} catch (err) {
console.error(`读取数据失败 key:${key}`, err);
return defaultValue;
}
}
}
// 使用示例
const appPrefs = new PreferenceHelper('app_settings');
await appPrefs.safePut('theme', 'dark');
let theme = await appPrefs.safeGet('theme', 'light');
6. 适用场景
- ✅ 适合:用户设置、应用配置、登录状态、简单的用户数据
- ❌ 不适合:大量结构化数据、复杂查询、关系型数据
总结
Preference首选项是鸿蒙应用开发中最简单易用的数据持久化方案,适合存储小规模的配置数据和用户偏好设置。通过合理的封装和错误处理,可以构建稳定可靠的数据存储逻辑。
本周内容
在鸿蒙(HarmonyOS)应用开发中,axios 是一个基于 Promise 的网络请求库,它可以帮助你更简洁、高效地处理 HTTP 请求 。下面我将为你介绍如何在鸿蒙项目中安装、配置和使用 axios。
🔧 安装与基础配置
在鸿蒙项目中使用 axios 前,你需要先完成安装和权限配置。
安装 Axios 在鸿蒙项目的根目录下,通过以下命令使用 OpenHarmony Package Manager (ohpm) 进行安装 :
ohpm install @ohos/axios配置网络权限 为了应用能够访问网络,你需要在
module.json5文件中声明网络权限 。"requestPermissions": [ { "name": "ohos.permission.INTERNET" } ]
🚀 发起网络请求
安装和配置完成后,你就可以开始使用 axios 发起网络请求了。
引入 Axios 在使用
axios的页面或工具文件中,首先需要引入它 :import axios from '@ohos/axios';发起 GET 请求 使用
axios.get方法发起 GET 请求 :axios.get('https://api.example.com/data') .then(response => { // 请求成功,处理响应数据 console.log(response.data); }) .catch(error => { // 请求失败,处理错误 console.error(error); });发起 POST 请求 使用
axios.post方法发起 POST 请求 :axios.post('https://api.example.com/submit', { name: 'Alice', age: 30 }) .then(response => { console.log('Submit Success:', response.data); }) .catch(error => { console.error('Request Failed:', error); });
💡 进阶用法与最佳实践
为了在大型项目中更好地管理网络请求,建议进行更完善的封装和配置。
创建 Axios 实例 你可以创建一个配置好的 Axios 实例,设置公共的基路径(baseURL)和超时时间 :
const instance = axios.create({ baseURL: 'https://api.yourdomain.com', // 你的接口基地址 timeout: 60000 // 超时时间,单位毫秒 });使用请求和响应拦截器 拦截器让你能在请求发出前或响应返回后,进行统一的预处理,例如自动添加身份验证令牌(Token)或统一处理错误 。
请求拦截器示例:
instance.interceptors.request.use((config) => { // 在发送请求前做些什么,例如添加token const token = '...'; // 从本地获取token的逻辑 if (token) { config.headers.token = token; // 将token添加到请求头 } return config; }, (error) => { // 对请求错误做些什么 return Promise.reject(error); });响应拦截器示例:
instance.interceptors.response.use((response: AxiosResponse) => { // 对响应数据做点什么,例如根据业务代码统一处理 let data = response.data; if (data.code === 200) { return data; // 业务成功,返回数据 } else { // 业务异常,可以在此显示Toast提示 console.error('Request failed with message:', data.msg); return Promise.reject(new Error(data.msg)); } }, (error) => { // 对响应错误做点什么,例如处理HTTP状态码非200的情况 console.error('Network error:', error); return Promise.reject(error); });对请求参数和响应数据进行类型约束 在 ArkTS 中,推荐使用泛型来定义请求参数和响应数据的类型,以获得更好的类型安全和代码提示 。
定义接口:
// 定义请求参数类型 interface LoginRequest { phone: string; passwd: string; } // 定义响应数据类型 interface LoginResponse { code: number; msg: string; token: string; }在请求中使用泛型:
// 在post请求中,三个泛型参数依次为:响应数据类型、AxiosResponse类型、请求参数类型 const response = await instance.post<LoginResponse, AxiosResponse<LoginResponse, null>, LoginRequest>('/user/login', { phone: '13166666666', passwd: 'yourpassword' }); console.log(response.token); // 此时有类型提示
💎 封装与实践建议
- 封装工具类:建议将
axios实例和通用配置封装成一个独立的工具类(如BaseRequest),方便在整个项目中统一管理和使用 。 - 结合业务逻辑:根据后端接口返回的数据结构,封装通用的响应类型,并抽取通用的请求方法,避免重复代码 。
axios 通过其简洁的 API、强大的拦截器机制和良好的类型支持,能够显著提升鸿蒙应用开发中网络请求的效率与可维护性 。希望这些信息能帮助你快速上手!如果你对特定场景下的使用方法有更多疑问,欢迎随时提出。
