本文面向初学者与一线开发,带你从一个空的 Entry 工程开始,按步骤实现“首次启动进入引导页、完成后进入主页面、支持主题持久化与用户数据存储”的完整功能。跟着做即可复现本项目功能。



entry、主页面 pages/Index 为例。在 entry/src/main/ets 下创建目录:
models/
utils/
pages/
└─ onboarding/
编辑文件:entry/src/main/resources/base/profile/main_pages.json
确保包含以下页面路径(缺失将导致“can’t find this page … path”错误):
{
"src": [
"pages/Index",
"pages/onboarding/WelcomeGuidePage",
"pages/onboarding/DataCollectionPage",
"pages/onboarding/CompletionPage"
]
}
文件:entry/src/main/ets/entryability/EntryAbility.ets
要点:
onCreate 中初始化 AppStorage 的全局主题键 app_is_dark_mode。onWindowStageCreate 中 loadContent('pages/Index')。代码示例(片段):
AppStorage.setOrCreate('app_is_dark_mode', false);
windowStage.loadContent('pages/Index');
文件:entry/src/main/ets/models/ThemeModel.ets
职责:
is_dark_mode。AppStorage('app_is_dark_mode'),供全局订阅。完整代码:
/**
* 主题模型 - 管理应用主题
*/
import { preferences } from '@kit.ArkData'
import { common } from '@kit.AbilityKit'
export class ThemeModel {
private isDarkMode: boolean = false
private preferencesInstance: preferences.Preferences | null = null
async loadThemeSettings(): Promise<void> {
try {
const context = getContext() as common.UIAbilityContext
this.preferencesInstance = await preferences.getPreferences(context, 'theme_preferences')
const saved = await this.preferencesInstance.get('is_dark_mode', false) as boolean
this.isDarkMode = saved
AppStorage.setOrCreate('app_is_dark_mode', this.isDarkMode)
} catch (error) {
console.error('ThemeModel', '加载主题设置失败:', error)
}
}
async toggleTheme(): Promise<void> {
try {
this.isDarkMode = !this.isDarkMode
AppStorage.setOrCreate('app_is_dark_mode', this.isDarkMode)
if (this.preferencesInstance) {
await this.preferencesInstance.put('is_dark_mode', this.isDarkMode)
await this.preferencesInstance.flush()
}
} catch (error) {
console.error('ThemeModel', '切换主题失败:', error)
}
}
getIsDarkMode(): boolean {
return this.isDarkMode
}
}
文件:entry/src/main/ets/utils/OnboardingManager.ets
职责:
initialize/hasShown/mark/reset。完整代码:
/** 引导页管理器 */
import { preferences } from '@kit.ArkData'
import { common } from '@kit.AbilityKit'
const PREFERENCES_NAME = 'onboarding_preferences'
const KEY_HAS_SHOWN_ONBOARDING = 'has_shown_onboarding'
export class OnboardingManager {
private static instance: OnboardingManager | null = null
private preferencesInstance: preferences.Preferences | null = null
private isInitialized: boolean = false
private constructor() {}
static getInstance(): OnboardingManager {
if (!OnboardingManager.instance) OnboardingManager.instance = new OnboardingManager()
return OnboardingManager.instance
}
async initialize(context: common.UIAbilityContext): Promise<void> {
if (this.isInitialized) return
this.preferencesInstance = await preferences.getPreferences(context, PREFERENCES_NAME)
this.isInitialized = true
console.info('OnboardingManager', '初始化成功')
}
async hasShownOnboarding(): Promise<boolean> {
if (!this.preferencesInstance) return false
try {
const hasShown = await this.preferencesInstance.get(KEY_HAS_SHOWN_ONBOARDING, false) as boolean
console.info('OnboardingManager', `引导页显示状态: ${hasShown}`)
return hasShown
} catch (e) {
console.error('OnboardingManager', '读取引导页状态失败:', e)
return false
}
}
async markOnboardingAsShown(): Promise<void> {
if (!this.preferencesInstance) return
await this.preferencesInstance.put(KEY_HAS_SHOWN_ONBOARDING, true)
await this.preferencesInstance.flush()
}
async resetOnboardingStatus(): Promise<void> {
if (!this.preferencesInstance) return
await this.preferencesInstance.put(KEY_HAS_SHOWN_ONBOARDING, false)
await this.preferencesInstance.flush()
}
}
文件:entry/src/main/ets/pages/onboarding/WelcomeGuidePage.ets
要点:
@Entry @Component 页面。关键片段:
@Entry
@Component
struct WelcomeGuidePage {
@State themeModel: ThemeModel = new ThemeModel()
@StorageProp('app_is_dark_mode') isDarkMode: boolean = false
async aboutToAppear() { await this.themeModel.loadThemeSettings() }
build() {
// ... UI,下一步:router.pushUrl({ url: 'pages/onboarding/DataCollectionPage' })
}
}
完整实现可参考本仓库同名文件。
文件:entry/src/main/ets/pages/onboarding/DataCollectionPage.ets
要点:
关键片段:
private async saveData() {
const context = getContext(this) as common.UIAbilityContext
const prefs = await preferences.getPreferences(context, 'onboarding_data')
await prefs.put('user_name', this.userName)
await prefs.put('selected_option', this.selectedOption)
await prefs.flush()
}
文件:entry/src/main/ets/pages/onboarding/CompletionPage.ets
要点:
OnboardingManager.markOnboardingAsShown()。pages/Index。关键片段:
const manager = OnboardingManager.getInstance()
await manager.initialize(getContext(this) as common.UIAbilityContext)
await manager.markOnboardingAsShown()
router.replaceUrl({ url: 'pages/Index' })
文件:entry/src/main/ets/pages/Index.ets
要点:
aboutToAppear 初始化主题并检查引导状态。replaceUrl 到欢迎页。关键片段:
async aboutToAppear() {
await this.themeModel.loadThemeSettings()
await this.checkOnboardingStatus()
}
setTimeout(() => {
router.replaceUrl({ url: 'pages/onboarding/WelcomeGuidePage' })
}, 100)
Column() { /* ... */ }
.width('100%').height('100%')
.backgroundColor(this.isDarkMode ? '#121212' : '#F5F5F5')
# DevEco Studio
Build > Build App(s)
Run 或 Shift + F10
hdc shell pm uninstall <你的包名>
# 或在代码中调用 OnboardingManager.resetOnboardingStatus()
main_pages.json 已注册所有引导页路径。.backgroundColor(...)。EntryAbility.onCreate 已初始化 AppStorage('app_is_dark_mode')。await prefs.flush() 已调用。本项目完整实现已包含在以下文件中,可直接对照复制:
entry/src/main/ets/models/ThemeModel.etsentry/src/main/ets/utils/OnboardingManager.etsentry/src/main/ets/pages/Index.etsentry/src/main/ets/pages/onboarding/WelcomeGuidePage.etsentry/src/main/ets/pages/onboarding/DataCollectionPage.etsentry/src/main/ets/pages/onboarding/CompletionPage.etsentry/src/main/resources/base/profile/main_pages.jsonentry/src/main/ets/entryability/EntryAbility.etspages/onboarding 下创建页面,并在 main_pages.json 注册,更新前一页的 router.pushUrl。@StorageProp('app_is_dark_mode') 动态切换颜色。DataCollectionPage 新增输入字段并在 saveData() 中持久化。到此,你已经完成了一个可用的 HarmonyOS 引导页系统。从架构、状态管理到页面编排、主题与存储,都具备了可扩展的实践基础。根据业务继续迭代即可上线使用。
源代码
https://gitcode.com/daleishen/onboarding
班级链接
https://developer.huawei.com/consumer/cn/training/classDetail/fd34ff9286174e848d34cde7f512ce22?type=1%3Fha_source%3Dhmosclass&ha_sourceId=89000248