在開發一個多頁面的Windows Phone 7應用程式的過程中,偶然發現與頁面導航(Page Navigation)有關的一些潛在“秘密”。
在我的應用程式中,頁面 A 的程式響應某按鈕的點擊事件,通過 NavigationService.Navigate() 方法跳轉到另一個頁面 B。而在 B 頁面中的 OnNavigatedTo 事件中,根據商務邏輯的需要,會進行一些判斷,然後在一些業務資料不滿足條件的情況下,會彈出訊息對話方塊(採用MessageBox.Show()方法)。這一操作流程似乎沒有什麼問題。但經過細心的測試發現,在該訊息對話方塊彈出後,如果使用者不做任何操作,大約10秒鐘後整個應用程式會被強行關閉。
而這一現象居然在聯機Debug時無法再現,只有通過應用程式列表直接運行起來才會發生!
經過反覆實驗和推測,我認為“強行關閉應用”這一步操作應該是由作業系統來處理的。再想想看,也相當合乎邏輯。我們可以嘗試在 B 頁面的 OnNavigatedTo 事件函數入口處設定一個斷點,然後在聯機 Debug 環境下觸發頁面跳轉。你會看到,在該事件被觸發的那一刻,頁面 A 仍顯示在手機螢幕中,表明頁面導航尚未結束,正處於進行過程中。而在此時彈出 MessageBox 對話方塊,恰恰阻礙了頁面跳轉的順利進行,使其處於“卡死”狀態(MessageBox.Show()方法會令程式流停止於該語句調用的地方,並在使用者對訊息對話方塊進行響應後繼續)。而根據 Windows Phone 7 的相關 Development Guide,頁面處於停滯狀態達10秒者,殺無論。這就解釋了為什麼在上述例子中,當使用者在10秒內不作出任何響應,應用程式就會被強行關閉了。
從這個角度出發,我們也不難猜想,如果在 OnNavigatedTo 事件中試圖執行一些“重量級”操作,導致進程停滯達10秒以上時,同樣也會被系統強行關閉。
用圖示來描述本文內容:
如果一定要在剛剛跳轉到 B 頁面時就執行必要的處理邏輯,並彈出 MessageBox 的話,可以考慮使用 B 頁面的 Loaded 事件。該事件的觸發時間稍晚於 OnNavigatedTo 事件,但此時整個頁面導航已經執行完畢,A 頁面已完全退出手機螢幕。因此,在 Loaded 事件裡彈出 MessageBox 是比較安全的。但值得注意的是,Loaded 事件僅在進入該頁面時觸發一次,而 OnNavigatedTo 事件則在每次顯示該頁面時都會被觸發(例如:在顯示 B 頁面的狀態下按 Start 按鈕或 Search 按鈕,然後再按下 Back 鍵回到 B 頁面時)。
有興趣的朋友可以下載範例程式碼來實測一下:
下載代碼
希望本文能夠給開發 Windows Phone 7 多頁面應用程式的朋友起到提醒的作用。