Flutter → ArkUI-X 页面转换指南(4)
本部分主要介绍
- 网络请求
- 数据持久化/状态管理
六、网络请求
Flutter 中使用插件 dio: ^5.8.0, ArkUI-X 中使用插件 @ohos/axios": ^2.2.12
1. 添加网络权限
文件:/entry/src/main/module.json5
{
"module": {
"name": "entry",
...
// 以下是添加网络权限的具体代码
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
}
}
2. 封装网络请求
文件:/entry/src/main/ets/network/HttpManager.ets
import axios, { InternalAxiosRequestConfig, AxiosResponse, AxiosError, AxiosInstance } from '@ohos/axios';
import { promptAction } from '@kit.ArkUI';
/* ------------------ 拦截器 ------------------ */
/**
* 请求拦截器:
*/
// 请求成功
function requestSuccessHandler(config: InternalAxiosRequestConfig) {
// 对请求数据做点什么
const token = 'token....'
if (token) {
config.headers['Authorization'] = 'Bearer ' + token //设置token
}
return config
}
// 请求失败
function requestFailHandler(error: AxiosError) {
// 对请求错误做些什么
return Promise.reject(error)
}
/**
* 响应拦截器:
*/
// 响应成功
function responseSuccessHandler(response: AxiosResponse) {
// 响应码 200 的处理
return response;
}
// 响应失败
function responseFailHandler(error: AxiosError) {
// 响应码 非200 的处理
return Promise.reject(error)
}
/* ------------------ 请求管理类 ------------------ */
// 创建实例
const instance: AxiosInstance = axios.create({
baseURL: 'http://localhost:8088/', // 请求地址
timeout: 300000, // 响应超时时间
headers: {
'Content-Type': 'application/json;charset=utf-8',
'Content-Language': 'en',
},
});
// 添加拦截器
instance.interceptors.request.use(requestSuccessHandler, requestFailHandler);
instance.interceptors.response.use(responseSuccessHandler, responseFailHandler);
// 封装请求方法
class HttpManager {
get<T>(url: string, params?: object): Promise<AxiosResponse<T>> {
return instance.get<T, AxiosResponse<T>>(url, { params })
}
// 封装post方法
post<T>(url: string, data?: object, config?: object): Promise<AxiosResponse<T>> {
return instance.post<T, AxiosResponse<T>>(url, data, config)
}
// 封装put方法
put<T>(url: string, data?: object, config?: object): Promise<AxiosResponse<T>> {
return instance.put<T, AxiosResponse<T>>(url, data, config)
}
// 封装delete方法
delete<T>(url: string, data?: object): Promise<AxiosResponse<T>> {
return instance.delete<T, AxiosResponse<T>>(url, data)
}
}
export const httpManager = new HttpManager();
七、数据持久化/状态管理
1. 应用数据持久化 Preferences
Flutter 中使用插件 shared_preferences: ^2.5.2, ArkUI-X 中使用原生的 Preferences
- 用户首选项(Preferences)为应用提供Key-Value键值型的轻量级数据处理能力,支持应用持久化轻量级数据,并对其修改和查询。
- Key 键为 string 类型,要求非空且长度不超过1024个字节。
- 如果 Value 值为 string 类型,请使用UTF-8编码格式,可以为空。
- 数据持久化需要在调用
preferences.put(key, value)后调用preferences.flush()接口以实现数据持久化。若不调用flush(),数据可能仅保存在内存中而不会写入持久化存储,导致应用退出后数据丢失。
封装数据持久化类 PreferencesManager
import { preferences } from '@kit.ArkData';
// 存储键名常量
export class PreferKeys {
static readonly USER_NAME = "username";
static readonly TOKEN = "token";
}
/**
* 应用数据持久化类
*/
class PreferencesManager {
// 首选项的实例
private dataPreferences: preferences.Preferences | null = null;
// 管理类的单例
private static instance: PreferencesManager;
// 获取单例
static getInstance(): PreferencesManager {
if (!PreferencesManager.instance) {
PreferencesManager.instance = new PreferencesManager();
}
return PreferencesManager.instance;
}
// 初始化:必须在应用启动时 (EntryAbility 中) 调用一次
init(entryAbilityContext: Context) {
// 应用数据持久化
let options: preferences.Options = { name: 'myStore' };
this.dataPreferences = preferences.getPreferencesSync(entryAbilityContext, options);
}
// 统一存储 (Put)
put(key: string, value: string | number | boolean) {
if (!this.dataPreferences) throw new Error('Preferences not initialized');
this.dataPreferences.putSync(key, value);
this.dataPreferences.flush(); // 确保写入磁盘
}
// 统一读取 (Get)
get(key: string, defaultValue: string | number | boolean) {
if (!this.dataPreferences) return defaultValue;
return (this.dataPreferences.getSync(key, defaultValue));
}
// 统一删除 (Delete)
delete(key: string) {
if (!this.dataPreferences) throw new Error('Preferences not initialized');
this.dataPreferences.deleteSync(key);
this.dataPreferences.flush();
}
}
export default PreferencesManager.getInstance();
初始化 ets/entryability/EntryAbility.ets 文件中
import PreferencesManager from '../storage/PreferencesManager';
export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage): void {
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
...
// 应用数据持久化
PreferencesManager.init(this.context);
...
}
}
页面中使用 ets/pages/login/LoginPage.ets
import PreferencesManager, { PreferKeys } from '../../storage/PreferencesManager';
@ComponentV2
export struct LoginPage {
...
// 初始化
aboutToAppear() {
// 获取缓存中数据
this.account = PreferencesManager.get(PreferKeys.USER_NAME, '') as string;
}
// 登陆
_handleLogin() {
// 将 token 存入缓存中
PreferencesManager.put(PreferKeys.TOKEN, this.account)
}
...
}
2. 组件状态管理
状态管理对比
| Flutter 状态管理 | ArkUI-X V1装饰器 | ArkUI-X V2装饰器 |
|---|---|---|
setState() | @State | @Local |
Widget 参数传递 | @Prop | @Param |
| 父子组件双向绑定 | @Link | @Param/@Event |
| -- | @ObjectLink | @Param |
Provider | @Provide | @Provider |
InheritedWidget | @Consume | @Consumer |
| -- | @Watch | @Monitor |
全局状态管理
| Flutter 状态管理 | ArkUI-X V1装饰器 | ArkUI-X V2装饰器 |
|---|---|---|
| -- | LocalStorage | @ObservedV2/@Trace |
| -- | AppStorage | AppStorageV2 |
| -- | PersistentStorage | PersistenceV2 |
示例代码
1)页面内部变量 setState 更新数据
// Flutter 组件
// 基本类型
int _selectedIndex = 0;
// 自定义对象
List<LanguageItem> _languageList = [];
// 赋值
@override
void initState() {
super.initState();
_languageList.add(new LanguageItem("繁體中文", false, "zh", "HK"));
_languageList.add(new LanguageItem("简体中文", false, "zh", "CN"));
_languageList.add(new LanguageItem("English", false, "en", "US"));
_selectedIndex = 1; // 真实情况是从缓存取一下
setState(() {});
}
// ArkUI-X 组件
// 基本类型
@Local _selectedIndex:number = 0;
// 自定义对象
@Local _languageList: Array<LanguageItem> = [];
/****** 生命周期 ******/
aboutToAppear() {
this._languageList.push({
title: "繁體中文",
isSelected: false,
languageCode: "zh",
countryCode: "HK"
})
this._languageList.push({
title: "简体中文",
isSelected: false,
languageCode: "zh",
countryCode: "CN"
})
this._languageList.push({
title: "English",
isSelected: false,
languageCode: "en",
countryCode: "US"
})
this._selectedIndex = 1;
}