📘 本篇目標是:在 GUI 信號機制基礎上,構建一個完整的“點擊按鈕 → 顯示加載動畫 → 異步加載數據 → 顯示結果”的響應式界面流程。通過協程掛起/恢復機制,實現清晰的異步邏輯,避免回調地獄。
🔁 回顧 Day 16:GUI 響應式信號機制
在 Day 16 中,我們學習了如何使用協程和信號機制處理 GUI 事件。主要內容包括:
- 按鈕點擊事件的處理:通過協程掛起,等待按鈕點擊事件的發生,然后恢復協程執行相應的邏輯。
- 信號機制的實現:使用
SignalHub
類管理不同的事件類型,實現事件的訂閱和觸發。 - 協程與 Dispatcher 的結合:確保協程的恢復在正確的線程中執行,避免線程安全問題。
這些基礎為我們今天的內容打下了堅實的基礎。
? 一、模擬加載動畫組件
我們首先創建一個簡單的加載動畫組件,用于在數據加載期間顯示加載狀態。
struct LoadingSpinner {void show() {std::cout << "🔄 顯示加載動畫...\n";}void hide() {std::cout << "? 隱藏加載動畫\n";}
};
? 二、構建異步數據加載器
接下來,創建一個模擬異步加載數據的函數,使用協程實現。
Task<std::string> loadDataAsync() {co_await std::suspend_always{}; // 模擬異步等待std::this_thread::sleep_for(std::chrono::seconds(2)); // 模擬加載時間co_return "數據加載完成";
}
? 三、構建按鈕點擊事件處理協程
我們創建一個協程函數,處理按鈕點擊事件,顯示加載動畫,加載數據,并在加載完成后更新界面。
Task<void> onButtonClick(LoadingSpinner& spinner) {spinner.show(); // 顯示加載動畫std::string data = co_await loadDataAsync(); // 異步加載數據spinner.hide(); // 隱藏加載動畫std::cout << "📦 加載結果: " << data << "\n";co_return;
}
? 四、主函數模擬用戶點擊按鈕
在主函數中,模擬用戶點擊按鈕,觸發上述協程。
int main() {LoadingSpinner spinner;std::cout << "🖱? 用戶點擊按鈕\n";auto task = onButtonClick(spinner); // 啟動協程處理按鈕點擊事件// 模擬事件循環while (!task.done()) {task.resume(); // 恢復協程執行}return 0;
}
輸出:
🖱? 用戶點擊按鈕
🔄 顯示加載動畫...
? 隱藏加載動畫
📦 加載結果: 數據加載完成
? 總結
通過以上步驟,我們實現了一個完整的響應式界面流程,使用協程清晰地表達了異步邏輯,避免了傳統回調方式帶來的復雜性。
🧠 鞏固練習題
Q1:如何確保協程 resume 在主線程執行?
A:使用主線程的 Dispatcher,在協程掛起時記錄 Dispatcher,resume 時通過 Dispatcher 調度回主線程。
Q2:如何處理多個按鈕點擊事件?
A:為每個按鈕創建獨立的協程處理函數,分別處理各自的點擊事件。
Q3:如何處理加載失敗的情況?
A:在 loadDataAsync
中添加異常處理邏輯,在協程中使用 try-catch
捕獲異常,進行相應的錯誤處理。
🔭 下一步 Day 18:構建響應式表單與數據驗證
- 創建響應式表單組件
- 使用協程處理表單輸入與驗證
- 實現異步提交與結果反饋