Treasure Case Sharing Of Harmonyos 5 Development — Practical Tips For Application Architecture

HarmonyOS Application Architecture Practice: Layered Design and Thread Communication Explained
Hello everyone! Today, let's talk about those architectural design techniques in HarmonyOS development that are 'mentioned in the official docs but hard to find in real projects.' Combining official documentation (Link 1, Link 2), I'll use real code examples and plain explanations to help you implement layered architecture and thread communication in your project, so you can say goodbye to 'knowing the theory but not the code'!
1. Layered Architecture: How to Use the Three-Layer Design?
HarmonyOS's layered architecture (Product Customization Layer, Basic Feature Layer, Common Capability Layer) is not just talk—the core is to reduce coupling and enable multi-end reuse. Let's look directly at the code structure:
MyApp/
│
├── entry/ # Product Customization Layer: Device-specific entry
│ ├── phone/ # Phone UI and logic
│ └── tablet/ # Tablet customization
│
├── features/ # Basic Feature Layer: Pluggable business modules
│ ├── news/ # News module (independent HAP)
│ └── settings/ # Settings module
│
└── common/ # Common Capability Layer
├── components/ # Common UI components
├── utils/ # Utility library
└── network/ # Network request encapsulation
Key Code Example:
1. Extracting Network Requests in the Common Capability Layer
// common/network/Request.ts
export class Request {
static async fetch(url: string): Promise<any> {
try {
const response = await http.createHttp().request(url);
return response.data;
} catch (err) {
// Unified error handling
console.error("Network error:", err);
}
}
}
2. Basic Feature Layer Calls Common Capability
// features/news/NewsViewModel.ts
import { Request } from '../../common/network/Request';
class NewsViewModel {
async loadNews() {
const data = await Request.fetch('https://api.news.com/list');
// Business logic processing...
}
}
3. Product Customization Layer Loads Modules by Device
// entry/phone/resources/base/profile/main_pages.json
{
"src": [
"pages/PhoneHome", // Phone home page
"pages/NewsPage?module=news" // Dynamically load news module
]
}
Why design like this?
- Need to change network requests? Just modify
common/network
, no impact on business code. - Add a new device (like a watch)? Copy
entry/phone
and change toentry/watch
for custom UI. - Remove the news module? Just remove the HAP package in
features/news
.
2. Thread Communication: How Can Sub-Threads Safely Update the UI?
HarmonyOS UI updates must be on the main thread (also called the UI thread), but time-consuming operations (network requests/database reads and writes) should be on sub-threads. The official recommendation is to use TaskDispatcher
and Emitter
for communication.
Practical Scenario: Sub-thread Gets Data → Main Thread Refreshes UI
// In ViewModel
import { emitter, TaskDispatcher } from '@ohos.base';
import { Request } from '../common/network/Request';
const UI_TASK_DISPATCHER = TaskDispatcher.getGlobalTaskDispatcher(TaskDispatcher.Priority.HIGH);
class UserViewModel {
private userId: string = '';
// 1. Get data in sub-thread
async fetchUserData() {
const backgroundTask: TaskDispatcher = TaskDispatcher.createBackgroundTaskDispatcher();
backgroundTask.asyncDispatch(() => {
const data = Request.fetch(`https://api.user.com/${this.userId}`);
// 2. Send data to main thread via Emitter
emitter.emit('USER_DATA_LOADED', data);
});
}
// 3. Main thread listens for events
setupEventListener() {
emitter.on('USER_DATA_LOADED', (data) => {
UI_TASK_DISPATCHER.asyncDispatch(() => {
// Safely update UI
this.userInfo = data;
AppStorage.setOrCreate('userName', data.name); // Bind to UI component
});
});
}
}
Pitfall Guide:
- Wrong example: Directly call
AppStorage.set()
in sub-thread → causes UI crash. - Correct way: Sub-thread sends event → main thread uses
asyncDispatch
to update data. - Performance optimization: Frequent updates? Use
@State
+@Watch
to refresh components locally.
3. Modular Design: When to Use HAP, HAR, or HSP?
The official docs often mention these concepts. In real development, use them like this:
Type | Scenario | Code Example |
---|---|---|
HAP | Independent feature module (e.g., settings) | Configure in build-profile.json with "type": "feature"
|
HAR | Common utility library (no UI) | Static library depended on by multiple HAPs |
HSP | Cross-app shared code | Declare shared: true
|
Dynamically Load HAP Module (Common in Plugin Architecture)
// Dynamically load news module in entry
import featureAbility from '@ohos.ability.featureAbility';
const moduleName = 'news';
featureAbility.dynamicImport(
`bundlename:${moduleName}`,
(err, data) => {
if (err) return;
// After successful load, jump to news page
router.pushUrl({ url: 'pages/NewsPage' });
}
);
4. Practical Tips Not Explicitly Stated in Official Docs
-
Prevent 'Pollution' in the Common Capability Layer:
- Prohibit reverse dependencies:
common
must not import code fromentry
orfeatures
. - How to check: Configure dependencies in
build-profile.json
:
- Prohibit reverse dependencies:
"dependencies": {
"features/news": ">=1.0.0",
"common": ">=1.0.0"
}
-
Killer for Multi-Device Adaptation:
Use
resource qualifiers
to distinguish devices, such as:-
news_page.phone.ets
→ News page for phone -
news_page.tablet.ets
→ Tablet version (large screen layout) Automatically matches device type for packaging at compile time!
-
Conclusion
HarmonyOS's layered and modular design takes some effort to set up initially, but it's really worth it for later maintenance! Suggestions:
- Firmly sink common code into the
common
layer; - After sub-thread operations, always use Emitter to update UI on the main thread;
- Try to split new features into HAPs for easy hot updates.
Encountered any pitfalls? Feel free to comment and discuss!
Keep encapsulation, refuse coupling, see you next time! ????
Popular Products
-
Gem's Ballet Natural Garnet Gemstone ...
$206.99$143.78 -
Soft Plush Teddy Bear Set for Valenti...
$63.99$43.78 -
Butt Lifting Body Shaper Shorts
$78.99$54.78 -
Slimming Waist Trainer & Thigh Trimmer
$57.99$39.78 -
Realistic Fake Poop Prank Toys
$24.99$16.78