當(dāng)我第一次接觸鴻蒙系統(tǒng)時,面對全新的開發(fā)環(huán)境和架構(gòu)概念,內(nèi)心既充滿期待又有些忐忑。回顧這段成長歷程,我希望通過分享自己的學(xué)習(xí)路徑和實踐經(jīng)驗,幫助更多開發(fā)者順利走進(jìn)鴻蒙的世界。
**初識鴻蒙:環(huán)境搭建與基礎(chǔ)認(rèn)知**
起步階段最重要的是正確搭建開發(fā)環(huán)境。我選擇使用DevEco Studio作為主要開發(fā)工具,這是專為鴻蒙應(yīng)用開發(fā)定制的集成開發(fā)環(huán)境。
```typescript
// 第一個鴻蒙應(yīng)用:Hello World
// entry/src/main/ets/entryability/EntryAbility.ts
import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
export default class EntryAbility extends UIAbility {
? onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
? ? console.log('EntryAbility onCreate');
? }
? onWindowStageCreate(windowStage: window.WindowStage): void {
? ? console.log('EntryAbility onWindowStageCreate');
? ? windowStage.loadContent('pages/Index', (err, data) => {
? ? ? if (err.code) {
? ? ? ? console.error('Failed to load the content. Cause: ' + JSON.stringify(err));
? ? ? ? return;
? ? ? }
? ? ? console.info('Succeeded in loading the content. Data: ' + JSON.stringify(data));
? ? });
? }
}
```
對應(yīng)的頁面布局文件:
```typescript
// entry/src/main/ets/pages/Index.ets
@Entry
@Component
struct Index {
? @State message: string = 'Hello HarmonyOS'
? build() {
? ? Row() {
? ? ? Column() {
? ? ? ? Text(this.message)
? ? ? ? ? .fontSize(50)
? ? ? ? ? .fontWeight(FontWeight.Bold)
? ? ? ? ? .onClick(() =><"1K.6370.HK"> {
? ? ? ? ? ? this.message = '歡迎來到鴻蒙世界!'
? ? ? ? ? })
? ? ? }
? ? ? .width('100%')
? ? }
? ? .height('100%')
? }
}
```
這個簡單的Hello World程序讓我理解了鴻蒙應(yīng)用的基本結(jié)構(gòu):Ability作為應(yīng)用組件,Page作為界面載體,通過聲明式UI構(gòu)建用戶界面。
**布局與組件:構(gòu)建用戶界面**
掌握了基礎(chǔ)后,我開始深入學(xué)習(xí)鴻蒙的UI組件系統(tǒng)。ArkTS語言結(jié)合聲明式語法,讓界面開發(fā)變得直觀而高效。
```typescript
// 綜合布局示例:用戶信息卡片
@Component
struct UserCard {
? @State isExpanded: boolean = false
? build() {
? ? Column() {
? ? ? // 用戶頭像和基本信息
? ? ? Row() {
? ? ? ? Image($r('app.media.user_avatar'))
? ? ? ? ? .width(60)
? ? ? ? ? .height(60)
? ? ? ? ? .borderRadius(30)
? ? ? ? Column() {
? ? ? ? ? Text('張三')
? ? ? ? ? ? .fontSize(20)
? ? ? ? ? ? .fontColor(Color.Black)
? ? ? ? ? Text('高級開發(fā)工程師')
? ? ? ? ? ? .fontSize(14)
? ? ? ? ? ? .fontColor(Color.Gray)
? ? ? ? }
? ? ? ? .alignItems(HorizontalAlign.Start)
? ? ? ? .margin({ left: 12 })
? ? ? ? Blank()
? ? ? ? Image($r(this.isExpanded ? 'app.media.arrow_up' : 'app.media.arrow_down'))
? ? ? ? ? .width(24)
? ? ? ? ? .height(24)
? ? ? ? ? .onClick(() => {
? ? ? ? ? ? this.isExpanded = !this.isExpanded
? ? ? ? ? })
? ? ? }
? ? ? .width('100%')
? ? ? .padding(16)
? ? ? // 可展開的詳細(xì)信息
? ? ? if (this.isExpanded) {
? ? ? ? Column() {
? ? ? ? ? Divider()
? ? ? ? ? Row() {
? ? ? ? ? ? Text('郵箱:')
? ? ? ? ? ? ? .fontSize(14)
? ? ? ? ? ? ? .fontColor(Color.Gray)
? ? ? ? ? ? Text('zhangsan@example.com')
? ? ? ? ? ? ? .fontSize<"2Y.6370.HK">(14)
? ? ? ? ? ? ? .fontColor(Color.Black)
? ? ? ? ? }
? ? ? ? ? .width('100%')
? ? ? ? ? .margin({ top: 8, bottom: 8 })
? ? ? ? ? Row() {
? ? ? ? ? ? Text('部門:')
? ? ? ? ? ? ? .fontSize(14)
? ? ? ? ? ? ? .fontColor(Color.Gray)
? ? ? ? ? ? Text('技術(shù)研發(fā)部')
? ? ? ? ? ? ? .fontSize(14)
? ? ? ? ? ? ? .fontColor(Color.Black)
? ? ? ? ? }
? ? ? ? ? .width('100%')
? ? ? ? ? .margin({ bottom: 8 })
? ? ? ? }
? ? ? ? .width('100%')
? ? ? ? .padding(16)
? ? ? }
? ? }
? ? .width('100%')
? ? .backgroundColor(Color.White)
? ? .borderRadius(12)
? ? .shadow({ radius: 8, color: '#1A000000', offsetX: 0, offsetY: 4 })
? ? .margin({ top: 12, left: 16, right: 16 })
? }
}
```
通過這個組件,我學(xué)會了狀態(tài)管理、條件渲染和事件處理等核心概念。
**數(shù)據(jù)管理與持久化存儲**
在實際應(yīng)用中,數(shù)據(jù)管理是必不可少的部分。我學(xué)習(xí)了鴻蒙提供的多種數(shù)據(jù)持久化方案。
```typescript
// 使用Preferences進(jìn)行輕量級數(shù)據(jù)存儲
import preferences from '@ohos.data.preferences';
@Entry
@Component
struct SettingsPage {
? @State username: string = ''
? @State notificationsEnabled: boolean = true
? private prefs: preferences.Preferences | null = null
? async aboutToAppear() <"3P.6370.HK">{
? ? try {
? ? ? this.prefs = await preferences.getPreferences(this.context, 'mySettings');
? ? ? this.username = await this.prefs.get('username', '');
? ? ? this.notificationsEnabled = await this.prefs.get('notificationsEnabled', true);
? ? } catch (err) {
? ? ? console.error('Failed to load preferences: ' + JSON.stringify(err));
? ? }
? }
? async saveSettings() {
? ? if (this.prefs) {
? ? ? await this.prefs.put('username', this.username);
? ? ? await this.prefs.put('notificationsEnabled', this.notificationsEnabled);
? ? ? await this.prefs.flush();
? ? ? promptAction.showToast({ message: '設(shè)置已保存' });
? ? }
? }
? build() {
? ? Column() {
? ? ? Text('應(yīng)用設(shè)置')
? ? ? ? .fontSize(24)
? ? ? ? .fontWeight(FontWeight.Bold)
? ? ? ? .margin({ top: 20, bottom: 30 })
? ? ? List({ space: 12 }) {
? ? ? ? ListItem() {
? ? ? ? ? Row() {
? ? ? ? ? ? Text('用戶名')
? ? ? ? ? ? ? .fontSize(18)
? ? ? ? ? ? TextInput({ placeholder: '請輸入用戶名', text: this.username })
? ? ? ? ? ? ? .onChange((value: string) => {
? ? ? ? ? ? ? ? this.username = value
? ? ? ? ? ? ? })
? ? ? ? ? }
? ? ? ? ? .padding(16)
? ? ? ? }
? ? ? ? ListItem() {
? ? ? ? ? Row() {
? ? ? ? ? ? Text('啟用消息通知')
? ? ? ? ? ? ? .fontSize(18)
? ? ? ? ? ? Toggle({ type: ToggleType.Switch, isOn: this.notificationsEnabled })
? ? ? ? ? ? ? .onChange((value: boolean) => {
? ? ? ? ? ? ? ? this.notificationsEnabled = value
? ? ? ? ? ? ? })
? ? ? ? ? }
? ? ? ? ? .padding(16)
? ? ? ? }
? ? ? }
? ? ? .layoutWeight(1)
? ? ? Button('保存設(shè)置')
? ? ? ? .width('90%')
? ? ? ? .height(48)
? ? ? ? .fontSize(18)
? ? ? ? .onClick(() =><"4G.6370.HK"> {
? ? ? ? ? this.saveSettings()
? ? ? ? })
? ? ? ? .margin({ bottom: 20 })
? ? }
? ? .width('100%')
? ? .height('100%')
? ? .backgroundColor('#F5F5F5')
? }
}
```
**網(wǎng)絡(luò)請求與數(shù)據(jù)交互**
現(xiàn)代應(yīng)用離不開網(wǎng)絡(luò)通信,我學(xué)習(xí)了如何在鴻蒙應(yīng)用中發(fā)起網(wǎng)絡(luò)請求并處理響應(yīng)。
```typescript
// 網(wǎng)絡(luò)請求封裝示例
import http from '@ohos.net.http';
class ApiService {
? private static instance: ApiService;
? private httpRequest: http.HttpRequest;
? private constructor() {
? ? this.httpRequest = http.createHttp();
? }
? static getInstance(): ApiService {
? ? if (!ApiService.instance) {
? ? ? ApiService.instance = new ApiService();
? ? }
? ? return ApiService.instance;
? }
? async get<T>(url: string, params?: Record<string, string>): Promise<T> {
? ? try {
? ? ? let fullUrl = url;
? ? ? if (params) {
? ? ? ? const queryParams = new URLSearchParams(params).toString();
? ? ? ? fullUrl += '?' + queryParams;
? ? ? }
? ? ? const response = await this.httpRequest.request(fullUrl, {
? ? ? ? method: http.RequestMethod.GET,
? ? ? ? connectTimeout: 60000,
? ? ? ? readTimeout: 60000,
? ? ? });
? ? ? if (response.responseCode === 200) {
? ? ? ? return JSON.parse(response.result as string) as T;
? ? ? } else {
? ? ? ? throw new Error(`HTTP ${response.responseCode}: ${response.result}`);
? ? ? }
? ? } catch (err) {
? ? ? console.error('Request failed: ' + JSON.stringify(err));
? ? ? throw err;
? ? }
? }
? async post<T>(url: string, data: object): Promise<T> {
? ? try {
? ? ? const response = await this.httpRequest.request(url, {
? ? ? ? method: http.RequestMethod.POST,
? ? ? ? header: {
? ? ? ? ? 'Content-Type': 'application/json',
? ? ? ? },
? ? ? ? extraData: JSON.stringify(data),
? ? ? ? connectTimeout: 60000,
? ? ? ? readTimeout: <"5D.6370.HK">60000,
? ? ? });
? ? ? if (response.responseCode === 200) {
? ? ? ? return JSON.parse(response.result as string) as T;
? ? ? } else {
? ? ? ? throw new Error(`HTTP ${response.responseCode}: ${response.result}`);
? ? ? }
? ? } catch (err) {
? ? ? console.error('Request failed: ' + JSON.stringify(err));
? ? ? throw err;
? ? }
? }
}
// 在組件中使用API服務(wù)
@Component
struct NewsList {
? @State newsItems: NewsItem[] = []
? @State isLoading: boolean = true
? async aboutToAppear() {
? ? await this.loadNews();
? }
? async loadNews() {
? ? try {
? ? ? this.isLoading = true;
? ? ? const api = ApiService.getInstance();
? ? ? this.newsItems = await api.get<NewsItem[]>('https://api.example.com/news');
? ? } catch (err) {
? ? ? console.error('Failed to load news: ' + JSON.stringify(err));
? ? ? promptAction.showToast({ message: '加載失敗,請重試' });
? ? } finally {
? ? ? this.isLoading = false;
? ? }
? }
? build() {
? ? Column() {
? ? ? if (this.isLoading) {
? ? ? ? LoadingProgress()
? ? ? ? ? .color(Color.Blue)
? ? ? ? ? .margin({ top: 20 })
? ? ? ? Text('加載中...')
? ? ? ? ? .fontSize(16)
? ? ? ? ? .margin({ top: 12 })
? ? ? } else {
? ? ? ? List({ space: 8 }) {
? ? ? ? ? ForEach(this.newsItems, (item: NewsItem) => {
? ? ? ? ? ? ListItem() {
? ? ? ? ? ? ? NewsCard({ item: item })
? ? ? ? ? ? }
? ? ? ? ? }, (item: NewsItem) => item.id.toString())
? ? ? ? }
? ? ? ? .layoutWeight(1)
? ? ? }
? ? }
? ? .width('100%')<"6M.6370.HK">
? ? .height('100%')
? }
}
```
**分布式能力探索**
鴻蒙的分布式特性是其核心優(yōu)勢之一,我花時間學(xué)習(xí)了如何實現(xiàn)跨設(shè)備協(xié)同。
```typescript
// 分布式數(shù)據(jù)管理示例
import distributedObject from '@ohos.data.distributedDataObject';
class DistributedSession {
? private session: distributedObject.DataObject;
? constructor(sessionId: string) {
? ? this.session = distributedObject.createDataObject(sessionId);
? ? // 監(jiān)聽數(shù)據(jù)變化
? ? this.session.on('change', (fields: string[]) => {
? ? ? console.info('分布式數(shù)據(jù)發(fā)生變化: ' + JSON.stringify(fields));
? ? ? // 通知界面更新
? ? ? this.notifyDataChange();
? ? });
? }
? // 設(shè)置共享數(shù)據(jù)
? setValue(key: string, value: any): void {
? ? this.session[key] = value;
? ? this.session.save().then(() => {
? ? ? console.info('數(shù)據(jù)保存成功');
? ? }).catch((err) => {
? ? ? console.error('數(shù)據(jù)保存失敗: ' + JSON.stringify(err));
? ? });
? }
? // 獲取共享數(shù)據(jù)
? getValue(key: string): any {
? ? return this.session[key];
? }
? // 設(shè)備狀態(tài)同步
? syncDeviceStatus(deviceId: string, status: DeviceStatus): void {
? ? this.setValue(`device_${deviceId}`, status);
? }
}
// 在組件中使用分布式能力
@Entry
@Component
struct CollaborativeWhiteboard {
? private distSession: DistributedSession = new DistributedSession('whiteboard_session');
? @State strokes: Stroke[] = []
? @State connectedDevices: string[] = []
? aboutToAppear() {
? ? this.distSession.setValue('whiteboard_data', this.strokes);
? }
? build() {
? ? Column() <"UF.5283.HK">{
? ? ? // 設(shè)備連接狀態(tài)顯示
? ? ? Row() {
? ? ? ? Text('協(xié)作設(shè)備:')
? ? ? ? ? .fontSize(16)
? ? ? ? ForEach(this.connectedDevices, (device: string) => {
? ? ? ? ? Text(device)
? ? ? ? ? ? .fontSize(14)
? ? ? ? ? ? .backgroundColor(Color.Green)
? ? ? ? ? ? .padding(4)
? ? ? ? ? ? .margin({ left: 8 })
? ? ? ? })
? ? ? }
? ? ? .padding(12)
? ? ? // 畫板區(qū)域
? ? ? Canvas(this.context)
? ? ? ? .width('100%')
? ? ? ? .height('80%')
? ? ? ? .backgroundColor(Color.White)
? ? ? ? .onTouch((event: TouchEvent) => {
? ? ? ? ? this.handleTouch(event);
? ? ? ? })
? ? ? // 工具欄
? ? ? Toolbar({
? ? ? ? onColorChange: (color: string) => this.setStrokeColor(color),
? ? ? ? onClear: () => this.clearWhiteboard()
? ? ? })
? ? }
? }
? private handleTouch(event: TouchEvent): void {
? ? // 處理觸摸事件并同步到其他設(shè)備
? ? const newStroke = this.createStrokeFromTouch(event);
? ? this.strokes.push(newStroke);
? ? this.distSession.setValue('whiteboard_data', this.strokes);
? }
}
```
**項目實戰(zhàn):天氣預(yù)報應(yīng)用**
將所學(xué)知識整合起來,我開發(fā)了一個功能完整的天氣預(yù)報應(yīng)用。
```typescript
// 主頁面組件
@Entry
@Component
struct WeatherApp {
? @State currentWeather: WeatherData | null = null
? @State forecast: ForecastItem[] = []
? @State currentCity: string = '北京市'
? async aboutToAppear() {
? ? await this.loadWeatherData();
? }
? async loadWeatherData() {
? ? try {
? ? ? const api = ApiService.getInstance();
? ? ? // 獲取當(dāng)前天氣
? ? ? this.currentWeather = await api.get<WeatherData>(
? ? ? ? `https://api.weather.com/current?city=${this.currentCity}`
? ? ? );
? ? ? // 獲取天氣預(yù)報
? ? ? this.forecast = await api.get<ForecastItem[]>(
? ? ? ? `https://api.weather.com/forecast?city=${this.currentCity}`
? ? ? );
? ? } catch (err) {
? ? ? console.error('Failed to load weather data: ' + JSON.stringify(err));
? ? }
? }
? build() {
? ? Column() {
? ? ? // 標(biāo)題欄
? ? ? Row() {
? ? ? ? Text('天氣預(yù)報')
? ? ? ? ? .fontSize(24)
? ? ? ? ? .fontWeight(FontWeight.Bold)
? ? ? ? ? .fontColor(Color.White)
? ? ? ? Blank()
? ? ? ? Button('切換城市')
? ? ? ? ? .fontSize(14)
? ? ? ? ? .backgroundColor(Color.Transparent)
? ? ? ? ? .fontColor(Color.White)
? ? ? ? ? .onClick(() => {
? ? ? ? ? ? this.showCitySelector();
? ? ? ? ? })
? ? ? }
? ? ? .width('100%')
? ? ? .padding(20)
? ? ? .backgroundColor(Color.Blue)
? ? ? Scroll() {
? ? ? ? Column() {
? ? ? ? ? // 當(dāng)前天氣信息
? ? ? ? ? if (this.currentWeather) {
? ? ? ? ? ? CurrentWeather({ weather: this.currentWeather })
? ? ? ? ? }
? ? ? ? ? // 天氣預(yù)報列表
? ? ? ? ? Text('未來預(yù)報')
? ? ? ? ? ? .fontSize(20)
? ? ? ? ? ? .fontWeight(FontWeight.Medium)
? ? ? ? ? ? .margin({ top: 24, bottom: 16, left: 16 })
? ? ? ? ? ForEach(this.forecast, (item: ForecastItem) => {
? ? ? ? ? ? ForecastRow({ item: item })
? ? ? ? ? })
? ? ? ? }
? ? ? }
? ? ? .layoutWeight(1)
? ? }
? ? .width('100%')
? ? .height('100%')
? }
}
```
通過這個完整的學(xué)習(xí)路徑,我從一個對鴻蒙開發(fā)一無所知的"小白",逐步成長為能夠獨立開發(fā)應(yīng)用的開發(fā)者。這個過程雖然充滿挑戰(zhàn),但每解決一個問題、每完成一個功能,都帶來了巨大的成就感。鴻蒙生態(tài)正在快速發(fā)展,我相信現(xiàn)在正是學(xué)習(xí)和參與的最佳時機。