Contents
Preface
-
What is Preferences
- Core Features
- Applicable Scenarios
-
Case Demonstration
- Feature Flow
- Effect Preview
-
Code Implementation
- Step 1: Project Initialization
- 1.1 Importing Required Modules
- 1.2 Defining Type APIs
- 1.3 Implementing Initialization Function
- 1.4 Lifecycle Integration
- Step 2: Loading Main Page Styles
- 2.1 Importing Dependency Modules
- 2.2 Implementing Style Loading Logic
- Step 3: Implementing Theme Settings Page
- 3.1 Full Page Code
- 3.2 Core Feature Analysis
- Key Takeaways
- Step 1: Project Initialization
-
Summary
- Core Points
- Practical Value
- Best Practice Recommendations
Preface
Hello everyone, I am Ruocheng. Welcome to the HarmonyOS Practical Development Series. This series aims to provide developers with hands-on technical solutions and ready-to-use code samples to help you quickly master core HarmonyOS app development skills.
This article dives into how to use Preferences for persistent storage so your app can remember user personalized settings. Let us explore this powerful and practical feature together.
What is Preferences
Preferences is a lightweight data storage solution provided by HarmonyOS, with the following characteristics:
Core Features
- Key-value storage:Stores data in a simple and efficient key-value format
- Data type support:Supports numbers, strings, booleans, and their array types
- Persistent storage:Data is automatically saved to the preferencesDir path and remains after app restart
- Lightweight design:Suitable for storing user configurations, app settings, and other lightweight data
Applicable Scenarios
- User personalized settings (such as theme and language)
- App configuration data
- User preference records
- Simple state preservation
Note: These APIs are supported starting from API version 9. Please ensure your development environment meets this requirement.
Case Demonstration
This example implements a theme color setting feature, showing the complete data persistence flow:
Feature Flow
- Homepage display:Render interface using the saved theme color
- Settings page:Offer multiple theme color options for users
- Data persistence:Automatically save settings upon selection
- Restart verification:Settings remain effective after app restart
Effect Preview
As shown in the figure below, users can enter the settings page from the homepage, select a preferred theme color, and after setting, even if the app is closed and reopened, the personalized setting persists, demonstrating true persistent storage.
Code Implementation
Step 1: Project Initialization
First, initialize in EntryAbility and set the default theme color. This ensures the app has a default style upon first launch.
1.1 Importing Required Modules
Import the necessary dependencies in the EntryAbility.ets file:
import { preferences } from '@kit.ArkData';
import {CustomStyle } from "../utils/types"
import { BusinessError } from '@kit.BasicServicesKit';
1.2 Defining Type APIs
Define the relevant TypeScript APIs in the ../utils/types file:
export interface CustomStyle{
setBgColor :string
}
export interface autoColor{color: string, name: string}
1.3 Implementing Initialization Function
Implement the custom style initialization logic in EntryAbility.ets:
async initCustomStyle(): Promise<void> {
try {
const pref = await preferences.getPreferences(this.context, 'customStyle');
const styleData = await pref.get('styleData', '');
if (!styleData) {
hilog.info(DOMAIN, 'testTag', 'No custom style found, saving default style.');
const defaultStyle: CustomStyle = {
setBgColor: '#F9F7F5',
};
await pref.put('styleData', JSON.stringify(defaultStyle));
await pref.flush();
hilog.info(DOMAIN, 'testTag', 'Default custom style has been saved successfully.');
} else {
hilog.info(DOMAIN, 'testTag', 'Custom style already exists.');
}
} catch (err) {
const error = err as BusinessError;
hilog.error(DOMAIN, 'testTag', `Failed to initialize custom style. Code is ${error.code}, message is ${error.message}`);
}
}
1.4 Lifecycle Integration
Call the initialization function in the onWindowStageCreate lifecycle.
Step 2: Loading Main Page Styles
2.1 Importing Dependency Modules
Import the required packages in the main page file:
import { preferences } from '@kit.ArkData';
import {CustomStyle } from "../utils/types"
import { BusinessError } from '@kit.BasicServicesKit';
2.2 Implementing Style Loading Logic
Write the core function to load and apply the theme color:
@State autoBgColor:string =''
async loadStyle() {
try {
const pref = await preferences.getPreferences(getContext(this), 'customStyle');
const styleDataString = await pref.get('styleData', '');
if (styleDataString) {
const styleData = JSON.parse(styleDataString as string) as CustomStyle;
this.autoBgColor = styleData.setBgColor;
}
} catch (err) {
const error = err as BusinessError;
console.error(`Failed to load custom style. Code is ${error.code}, message is ${error.message}`);
}
}
aboutToAppear(): void {
this.loadStyle();
}
onPageShow(): void {
this.loadStyle();
}
Code explanation:
- Call the loadStyle() method in the aboutToAppear and onPageShow lifecycle methods.
- Use preferences.getPreferences() to obtain the storage instance.
- Use the pref.get() method to read saved style data.
- Parse the JSON string into an object and apply it to the interface.
Step 3: Implementing Theme Settings Page
3.1 Full Page Code
For ease of understanding and use, below is the full implementation of the theme settings page:
import {autoColor,CustomStyle } from "../utils/types"
import { preferences } from '@kit.ArkData';
import { BusinessError } from '@kit.BasicServicesKit';
import { promptAction, router, Router } from "@kit.ArkUI";
@Entry
@Component
struct Theme {
// Define 18 different color data
private colorData: autoColor[] = [
{ color: '#FF8C00', name: 'DarkOrange' },
{ color: '#FF6347', name: 'Tomato' },
{ color: '#32CD32', name: 'LimeGreen' },
{ color: '#1E90FF', name: 'DodgerBlue' },
{ color: '#FF1493', name: 'DeepPink' },
{ color: '#9370DB', name: 'MediumPurple' },
{ color: '#FFD700', name: 'Gold' },
{ color: '#20B2AA', name: 'LightSeaGreen' },
{ color: '#FF4500', name: 'OrangeRed' },
{ color: '#8A2BE2', name: 'BlueViolet' },
{ color: '#00CED1', name: 'DarkTurquoise' },
{ color: '#FF69B4', name: 'HotPink' },
{ color: '#7FFF00', name: 'Chartreuse' },
{ color: '#DC143C', name: 'Crimson' },
{ color: '#00BFFF', name: 'DeepSkyBlue' },
{ color: '#DA70D6', name: 'Orchid' },
{ color: '#FFA500', name: 'Orange' },
{ color: '#40E0D0', name: 'Turquoise' }
]
// Define the app color
async handleApplyBgColor(color:string){
const autoColor:CustomStyle ={
setBgColor:color
}
try {
// Get the preference instance
const pref = await preferences.getPreferences(getContext(this), 'customStyle');
// Convert the style object to a string and store it
await pref.put('styleData', JSON.stringify(autoColor));
// Refresh data to disk
await pref.flush();
console.info('Custom style setting succeeded');
this.getUIContext().getPromptAction().showToast({
message: "Custom style setting succeeded",
duration: 2000,
showMode: promptAction.ToastShowMode.DEFAULT,
bottom: 80
});
} catch (err) {
const error = err as BusinessError;
this.getUIContext().getPromptAction().showToast({
message: "Custom style setting failed",
duration: 2000,
showMode: promptAction.ToastShowMode.DEFAULT,
bottom: 80
});
console.error(`Setting failed ${error.code}, ${error.message}`);
}
}
@Builder
ColorCard(colorInfo:autoColor) {
Column() {
// Color display area
Row()
.width('100%')
.height(60)
.backgroundColor(colorInfo.color)
.borderRadius({
topLeft: 8,
topRight: 8,
bottomLeft: 0,
bottomRight: 0
})
// Information display area
Column() {
Text(colorInfo.color)
.fontSize(12)
.fontWeight(FontWeight.Bold)
.fontColor('#333333')
.margin({ top: 6 })
Text(colorInfo.name)
.fontSize(10)
.fontColor('#666666')
.margin({ top: 2, bottom: 6 })
}
.width('100%')
.backgroundColor('#FFFFFF')
.borderRadius({
topLeft: 0,
topRight: 0,
bottomLeft: 8,
bottomRight: 8
})
}
.width('100%')
.backgroundColor('#FFFFFF')
.borderRadius(8)
.shadow({
radius: 4,
color: '#1A000000',
offsetX: 0,
offsetY: 1
})
.onClick(()=>{
this.handleApplyBgColor(colorInfo.color)
})
}
build() {
Column() {
Row(){
Button('Back').onClick(()=>{
router.replaceUrl({
url:'pages/Index'
})
})
}
Text('Color theme')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 16 })
.fontColor('#333333')
// Use Grid layout, 4-column display
Grid() {
ForEach(this.colorData, (item: autoColor, index: number) => {
GridItem() {
this.ColorCard(item)
}
.padding(4)
})
}
.columnsTemplate('1fr 1fr 1fr 1fr') // 4 equally sized columns
.rowsGap(8)
.columnsGap(8)
.padding({ left: 12, right: 12 })
.layoutWeight(1)
}
.height('100%')
.width('100%')
.backgroundColor('#F8F8F8')
}
}
3.2 Core Feature Analysis
Theme color application function — key implementation of data persistence:
// Define the app color
async handleApplyBgColor(color:string){
const autoColor:CustomStyle ={
setBgColor:color
}
try {
// Get the preference instance
const pref = await preferences.getPreferences(getContext(this), 'customStyle');
// Convert the style object to a string and store it
await pref.put('styleData', JSON.stringify(autoColor));
// Refresh data to disk
await pref.flush();
console.info('Custom style setting succeeded');
this.getUIContext().getPromptAction().showToast({
message: "Custom style setting succeeded",
duration: 2000,
showMode: promptAction.ToastShowMode.DEFAULT,
bottom: 80
});
} catch (err) {
const error = err as BusinessError;
this.getUIContext().getPromptAction().showToast({
message: "Custom style setting failed",
duration: 2000,
showMode: promptAction.ToastShowMode.DEFAULT,
bottom: 80
});
console.error(`Setting failed ${error.code}, ${error.message}`);
}
}
Key steps description:
- Create a data object:Encapsulate the user-selected color into a CustomStyle object
- Get storage instance:Get the storage instance named 'customStyle' using preferences.getPreferences()
- Data serialization:Use JSON.stringify() to convert objects into string format
- Write data:Call the pref.put() method to write data into storage
- Persistent storage:Use pref.flush() to ensure that data is written to disk immediately
- User feedback:Use a Toast message to inform users of the operation result
Key Takeaways
In simple terms, persistent storage using preferences mainly involves storing and retrieving data.
Store
// Get the preference instance
const pref = await preferences.getPreferences(getContext(this), 'customStyle');
// Convert the style object to a string and store it
await pref.put('styleData', JSON.stringify(autoColor));
// Refresh data to disk
await pref.flush();
Retrieve
const pref = await preferences.getPreferences(getContext(this), 'customStyle');
const styleDataString = await pref.get('styleData', '');
Simple, isn't it? Once you master persistent storage, you can use it for a wide variety of features.
Summary
Through this article, we have learned the complete flow of using Preferences in HarmonyOS.
Core Points
- Simple and easy to use:Preferences provides a clean and lightweight key-value storage mechanism ideal for simple data persistence
- Lifecycle integration:Make good use of component lifecycle events to ensure timely data loading and app
- Error handling:Robust exception handling improves both app stability and user experience
- Data synchronization:Use flush() to make sure data is written to disk immediately, avoiding data loss
Practical Value
- Enhanced user experience:Retains users' personalized settings for a consistent experience
- Improved development efficiency:Simple APIs enable quick implementation of data persistence
- Broad use cases:Suitable for theme customization, user preferences, app configuration, and more.
Best Practice Recommendations
- Wise data structures planning:Design clear and maintainable APIs for easier scalability.
- Asynchronous processing:Use async/await to process asynchronous operations and prevent blocking the main thread.
- User feedback:Always inform users of operation results to enhance the interaction experience.
- Error handling:Perfect error handling and logging for easy troubleshooting
We hope this article helps you quickly master the usage of Preferences and apply this powerful data storage feature flexibly in your own projects. That's all for today — class dismissed.




Top comments (0)