鴻蒙案例實踐:智慧家居控制皮膚的併發任務與UI互動設計

SameX發表於2024-10-26

本文旨在深入探討華為鴻蒙HarmonyOS Next系統(截止目前API12)的技術細節,基於實際開發實踐進行總結。主要作為技術分享與交流載體,難免錯漏,歡迎各位同仁提出寶貴意見和問題,以便共同進步。本文為原創內容,任何形式的轉載必須註明出處及原作者。

1. 專案概述與需求分析

背景
隨著物聯網(IoT)的發展,智慧家居系統越來越普及,使用者可以透過手機或平板等裝置對家庭中的各種裝置進行控制,如燈光、空調、窗簾等。為了讓使用者能夠更加便捷地控制這些裝置,要求開發一個智慧家居控制皮膚應用,能夠非同步控制多臺裝置,並實時反饋裝置狀態到使用者介面。

需求

  • 使用者可以透過控制皮膚的按鈕控制智慧燈、空調和窗簾。
  • 裝置的控制是非同步的,避免阻塞主執行緒影響使用者體驗。
  • 每個裝置的狀態(開啟、關閉)應及時反饋到 UI 介面上。
  • 介面互動應簡潔流暢,並具有良好的使用者體驗。
  • 需要處理裝置無法響應或出錯的情況,並透過 UI 提示給使用者。

2. 技術分析

關鍵技術

  • ArkUI 的宣告式 UI 程式設計:宣告式程式設計能夠簡化 UI 的開發,狀態的變更可以自動觸發介面重新整理,減少手動操作和邏輯耦合。
  • @Concurrent 裝飾器:用於非同步執行控制裝置的任務,避免裝置控制時的阻塞,保證使用者介面的流暢性。
  • TaskPool 併發任務排程:透過 TaskPool 進行任務的管理與排程,支援高效的多執行緒任務執行。
  • Promise 非同步處理:處理非同步任務的執行結果並捕獲可能發生的異常,確保操作失敗時能夠正確處理。
  • 狀態管理:透過 ArkUI 的狀態管理機制實現裝置狀態的跟蹤與 UI 的自動更新。

設計考慮

  • 效能:裝置控制和狀態反饋是非同步的,避免阻塞 UI 執行緒,提升效能。
  • 容錯性:確保裝置控制時能處理裝置響應失敗的情況,避免影響使用者體驗。
  • 模組化:每個裝置的控制任務應獨立,並且可以擴充套件更多裝置。

3. 整體架構設計

架構層次

  1. UI 層

    • 負責介面展示與使用者互動,包括按鈕點選和狀態顯示。
    • 使用 ArkUI 的宣告式 UI 程式設計,實現裝置狀態的實時反饋。
  2. 邏輯層

    • 負責控制裝置的業務邏輯,實現裝置的開關控制。
    • 使用 @Concurrent 裝飾器非同步執行裝置控制,任務由 TaskPool 排程。
  3. 資料層

    • 模擬裝置的狀態資訊(例如“開啟”或“關閉”),並透過 Promise 的返回值告知裝置操作是否成功。

模組劃分

  1. 裝置控制模組

    • 每個裝置(燈、空調、窗簾)都有獨立的控制邏輯模組,確保模組之間解耦,便於擴充套件新裝置。
  2. 狀態管理模組

    • 透過 ArkUI 狀態管理功能,跟蹤裝置當前的狀態,並根據狀態變化自動更新 UI。
  3. 異常處理模組

    • 在裝置控制過程中可能出現的異常,如裝置無法連線、操作失敗等,這些異常將被捕獲並反饋到 UI 層,使用者可以清楚瞭解裝置的操作狀態。

架構圖示意

--------------------------------------
|           UI層 (ArkUI)             |
|------------------------------------|
| 裝置控制按鈕 | 狀態顯示 | 錯誤提示  |
--------------------------------------
|         邏輯層 (併發控制)           |
|------------------------------------|
| @Concurrent 併發任務執行            |
| TaskPool 任務排程與執行            |
--------------------------------------
|         資料層 (裝置模擬)           |
|------------------------------------|
| Promise 非同步處理與狀態反饋          |
--------------------------------------

4. 軟體設計

在軟體設計中,我們將專案劃分為幾個獨立的模組來處理不同的功能需求。

4.1 UI 設計與狀態管理

UI 部分使用 ArkUI 的宣告式程式設計,將裝置控制按鈕與狀態顯示模組化。每個按鈕觸發一個裝置控制任務,狀態則透過 ArkUI 的 @State 自動繫結到 UI。

@State lightStatus: string = '關閉'
@State acStatus: string = '關閉'
@State curtainStatus: string = '關閉'

4.2 非同步併發任務設計

每個裝置控制任務都透過 @Concurrent 裝飾器來宣告為併發任務,這樣可以確保操作不會阻塞主執行緒。任務的實際執行由 TaskPool 管理,這樣可以併發執行多個裝置的操作,提升響應速度。

@Concurrent
async function executeConcurrentTask(device: string): Promise<string> {
  // 模擬裝置操作
}

4.3 狀態反饋與 UI 更新

裝置狀態的更新透過 Promise 非同步返回,並將返回值更新到繫結的狀態變數中,UI 自動根據狀態變化進行重新整理,無需手動更新 UI。

executeConcurrentTask('light').then(status => {
  this.lightStatus = status;
}).catch(error => {
  console.error('燈控制失敗: ' + error.message);
});

4.4 異常處理與容錯設計

裝置控制過程中可能會遇到裝置無法響應或出現其他錯誤。在 Promise 中捕獲這些異常,並透過 catch 回撥將錯誤反饋到使用者介面。

try {
  // 控制裝置
} catch (error) {
  return `操作失敗: ${error.message}`;
}

4.5 模組化設計

系統採用模組化設計,每個裝置的控制邏輯獨立,便於擴充套件。當需要增加新的裝置時,只需增加對應的裝置控制函式,並在 UI 層增加一個按鈕與狀態繫結即可。


5. 任務執行與狀態反饋示例

下面是 TaskPool 中執行併發任務,並更新 UI 狀態的程式碼示例:

async function controlLight() {
  let task: taskpool.Task = new taskpool.Task(executeConcurrentTask, 'light');
  taskpool.execute(task).then(result => {
    this.lightStatus = result as string;
  }).catch(error => {
    console.error("任務執行失敗: " + error);
  });
}

6. 綜合示例程式碼

完整的智慧家居控制皮膚應用實現,包含 UI 層、非同步任務層以及錯誤處理機制。

@Entry
@Component
struct ControlPanel {
  @State lightStatus: string = '關閉'
  @State acStatus: string = '關閉'
  @State curtainStatus: string = '關閉'

  build() {
    Column() {
      Row() {
        Button('控制燈')
          .onClick(() => {
            controlLight();
          })
        Text('燈狀態: ' + this.lightStatus)
      }
      Row() {
        Button('控制空調')
          .onClick(() => {
            controlAC();
          })
        Text('空調狀態: ' + this.acStatus)
      }
      Row() {
        Button('控制窗簾')
          .onClick(() => {
            controlCurtain();
          })
        Text('窗簾狀態: ' + this.curtainStatus)
      }
    }
  }

  controlLight() {
    executeConcurrentTask('light').then(status => {
      this.lightStatus = status;
    }).catch(error => {
      console.error('燈控制失敗: ' + error.message);
    });
  }

  controlAC() {
    executeConcurrentTask('ac').then(status => {
      this.acStatus = status;
    }).catch(error => {
      console.error('空調控制失敗: ' + error.message);
    });
  }

  controlCurtain() {
    executeConcurrentTask('curtain').then(status => {
      this.curtainStatus = status;
    }).catch(error => {
      console.error('窗簾控制失敗: ' + error.message);
    });
  }
}

@Concurrent
async function executeConcurrentTask(device: string): Promise<string> {
  try {
    switch (device) {
      case 'light':
        await delay(1000);
        return '已開啟';
      case 'ac':
        await delay(2000);
        return '已開啟';
      case 'curtain':
        await delay(1500);
        return '已開啟';
      default:
        throw new Error('未知裝置');
    }
  } catch (error) {
    return `操作失敗: ${error.message}`;
  }
}

function delay(ms: number) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

7. 總結

在這篇文章中,吾嘗試設計並實現了一個智慧家居控制皮膚應用,展示了 ArkTS 結合 ArkUI 的強大功能。透過併發任務的使用,系統能夠同時控制多個裝置,並實時反饋狀態。同時,應用良好的狀態管理與容錯設計,提升了使用者體驗和系統穩定性。這為未來更多智慧家居應用的開發奠定了基礎。

相關文章