Flipper Zero 宇宙最強攻略:30 天帶你從入門到入坑 Day28 - 會寫完喔!倒數 48 小時的勝利宣言,即將踏上終點的鐵人賽之旅!
Cover
圖片來源:https://artprojectsforkids.org/how-to-draw-a-dolphin/
資安倫理宣導
請注意,透過 Flipper Zero 學習的資訊技術與知識,目的在於提升個人的技術能力和資安意識。我們強烈呼籲大家,絕對不要使用所學知識從事任何違法行為。您的合法使用是我們的期望,也是您自身責任的
一部分。
開發倒數 48 小時
SceneManager and ViewDispatcher
我們要繼續提到 SceneManager 透過一系列的 scene_manager_*
開頭的函式來管理應用程式中的所有場景細節。主要是確保當進入場景、離開場景或接收到新事件時,相關的處理函式會被正確的呼叫。
另一個是 ViewDispatcher 是使用許多 view_dispatcher_*
的函式來管理 views。這些函式會在 SceneManager 中被呼叫。總之,ViewDispatcher 是負責處理場景中 Views 的顯示和管理。
當我們在定義應用程式場景時,應提供所有場景處理函式作為一個 SceneManagerHandlers 結構傳給 scene_manager_alloc
函式。例如說作者這邊的場景會用數字做為索引,同時為了方便追蹤這些場景,通常我們會定義一個 enum 類型來表示場景的索引,像是:
1 | typedef enum { |
像是這邊的 count 只要放在枚舉的最後一項,之後增加或是修改場景數量的時候都可以輕鬆算出場景的總數。
而視圖是可以重複使用的,因此應用程式中可能場景數量會比視圖更多。換句話說,我們有可能一個視圖對應多個場景:
1 | typedef enum { |
這樣也提高了資源利用率。
初始化應用程式
首先我們會在 test_app_init
函式裡面初始化 scene manager 以及 view dispatcher:
1 | TestApp* app = malloc(sizeof(TestApp)); |
設定 Scene Manager
1 | app->scene_manager = scene_manager_alloc(&test_app_scene_event_handlers, app); |
我們為 SceneManager 分配記憶體。
其中這邊的第二個參數是 context,當場景處理方法被調用時,會回傳這個 context,第一個參數是 SceneManagerHandlers* test_app_scene_event_handlers
已經提前定義好並包含 on_enter
、on_exit
、on_event
處理函式集合。
處理函式集合
on_enter_handlers
:當進入某個場景時會調用這個處理函式集合,它包含了所有場景的進入處理邏輯。這些函式與定義的 enum 順序一致。例如,進入主選單或彈出視窗時會調用對應的進入函數。
1 | void (*const test_app_scene_on_enter_handlers[])(void*) = { |
on_event_handlers
:當某個場景處於活動狀態時,並且收到了事件(如使用者操作),會調用這個事件處理函式集合。每個場景有其專屬的事件處理邏輯,也是與 enum 順序一致。
1 | bool (*const test_app_scene_on_event_handlers[])(void*, SceneManagerEvent) = { |
on_exit_handlers
:當離開某個場景時,會調用這個處理函式集合。這些函式負責處理場景退出時的清理或其他工作,同樣是與 enum 順序保持一致。
1 | void (*const test_app_scene_on_exit_handlers[])(void*) = { |
test_app_scene_event_handlers
:這是所有場景處理器的集合,包含 on_enter
、on_event
和 on_exit
的處理函數。這樣的結構可以確保每個場景的進入、事件處理和退出邏輯都能正確運行。
1 | const SceneManagerHandlers test_app_scene_event_handlers = { |
設定 View Dispatcher
test_app_view_dispatcher_init
函式負責初始化視圖分發器,這部分稍微複雜一點。具體的步驟如下:
- 首先我們要先分配一個視圖分發器,用來管理應用程式中的不同視圖:
1
app->view_dispatcher = view_dispatcher_alloc();
- 接著,我們需要啟用隊列功能,讓視圖分發器能夠依序處理事件。
1
view_dispatcher_enable_queue(app->view_dispatcher);
- 然後我們需要為應用程式中的各個視圖分配記憶體,這裡我們分別為菜單和彈出視窗進行分配:
1
2app->menu = menu_alloc();
app->popup = popup_alloc(); - 接著我們將事件從視圖傳遞到場景管理器,因為視圖本身會處理事件和導航功能,但我們希望這些事件能夠傳遞到場景管理器,使得目前處於活躍狀態的場景能夠接收到並處理這些事件。因此我們需要設置事件回調函式來將事件傳遞到場景管理器。
1
2
3
4
5
6
7
8// 設置回調函式,將事件從視圖傳遞到場景管理器
view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
view_dispatcher_set_custom_event_callback(
app->view_dispatcher,
test_app_scene_manager_custom_event_callback);
view_dispatcher_set_navigation_event_callback(
app->view_dispatcher,
test_app_scene_manager_navigation_event_callback); - 最後,我們需要將視圖註冊到視圖分發器,並且將它們與各自的列舉值進行對應。這樣,當我們需要切換到特定視圖時,系統能夠正確處理視圖之間的切換。
1
2
3
4
5
6
7
8
9
10// 將視圖添加到分發器,並根據它們的列舉值進行索引
view_dispatcher_add_view(
app->view_dispatcher,
TestAppView_Menu,
menu_get_view(app->menu));
view_dispatcher_add_view(
app->view_dispatcher,
TestAppView_Popup,
popup_get_view(app->popup));
按讚訂閱收藏小鈴噹叮叮叮
今天就先到這邊,預計明天走完教學,後天做出自已的 app。
各位明天見!
References
- Title: Flipper Zero 宇宙最強攻略:30 天帶你從入門到入坑 Day28 - 會寫完喔!倒數 48 小時的勝利宣言,即將踏上終點的鐵人賽之旅!
- Author: kazma
- Created at : 2024-10-12 21:17:31
- Updated at : 2024-10-27 17:34:56
- Link: https://kazma.tw/2024/10/12/Flipper-Zero-宇宙最強攻略:30-天帶你從入門到入坑-Day28/
- License: This work is licensed under CC BY-NC-SA 4.0.