IT之家學院:如何解決UWP應用易閃退的問題
UWP應用,全稱或許可稱Windows通用平台應用,是微軟推出的新一代Windows應用開發模型。但是自推出以來,卻飽受詬病,其中,易閃退是很多人對它的第一印象。今天,我們就來談一談UWP應用閃退的問題,並教你如何解決它。
本文所述是立於開發者角度,即從應用代碼解決問題。而非處於用戶角度,在應用之外解決UWP應用閃退的問題
大部分閃退的根源
UWP應用不是瓷娃娃,沒那麼易碎。「閃退」,歸根結蒂其實是Windows對系統的保護,避免因應用而干擾到系統運行。這種處理方式是站在系統角度上的,但開發者和用戶都不領情。
用戶自不必說,應用閃退,極大地影響用戶體驗,閃退了幾次就把軟體卸載了,閃退的應用多了,連帶著對整個UWP應用都討厭上了。
而開發者也很糾結,用戶抱怨出現閃退,可在開發者這裡沒辦法復現,導致開發者調試困難,有時候也是不了了之。
那麼大部分閃退的根源是什麼呢?
一言以蔽之,就是出現了未捕獲的異常,即UnhandledException。
在寫應用的時候,出現錯誤的原因多種多樣,從大的架構設計失當,到小的出現了不安全的空(Null)值。這些錯誤,開發者有的可以在程序設計時就利用`try-catch`語句進行捕獲,經驗越豐富的程序員,設計時考慮到的可能異常就越多。但是人力有時窮,不可能方方面面都考慮到,而程序一旦在運行過程中出現了**未捕獲的異常**,應用馬上閃退,毫無二話。
照這樣說,出現未捕獲的異常似乎是再所難免的,可為什麼有些應用基本不閃退呢?是它們的程序全身上下都是try-catch嗎?
肯定不是啦~
解決未捕獲的異常非常簡單,即便算上大括弧,也只需要5行代碼就可以搞定。
如何一勞永逸地解決閃退問題
如上節所述,絕大部分閃退的根源是未捕獲的異常。既然是未捕獲,那我們把它捕獲了不就完事了嗎?
說起來簡單,做起來……更簡單!
每一個新建的UWP應用都有一個App.xaml的文件,其背後則有一個App.xaml.cs。
App.xaml.cs中包含著關於應用啟動、暫停等應用層級的操作邏輯,這個我相信各位開發者都是知道的。而所有未捕獲的異常,最終都會冒泡到這裡,所以這裡是最後一關。換句話說,我們只要在這裡設一道卡,抓住這個異常,不讓它觸發閃退機制就萬事大吉了。
App類派生自Application類,且自帶了一個事件,就是UnhandledException,說明是**當異常可由應用程序代碼處理,如從本機級別的Windows運行時錯誤轉發時發生。應用程序可標記事件數據中處理的匹配項**。
換句話說,人家早就想到會有閃退這種情況,已經預先把這個事件給你定好了。那我們要做的就非常簡單了。
首先,在App的構造函數里加上
this.UnhandledException += OnUnhandledException;
給這個事件綁定上一個處理函數。
接下來,我們就來寫這個處理函數:
private void OnUnhandledException(object sender, Windows.UI.Xaml.UnhandledExceptionEventArgs e)
{
e.Handled = true;
}
就這樣,因出現未捕獲的異常而造成的閃退就解決了,這個原因的閃退佔了總體的九成以上。可以說,接下來,只要你的應用不作死,不故意寫點死循環,不搞不安全的騷操作,基本上就不會再閃退了。
閃退問題的後續處理
出現閃退,意味著程序有錯誤未捕獲。既然有錯誤,那就要解決。單靠一個e.Hanled=true;……
這種粗暴的解決方式雖然能夠一次性解決閃退問題,但是治標不治本(雖然用戶並不清楚,但實際使用體驗卻有了不少的提升)。作為軟體的設計者,我們依然需要知道具體是哪裡出現了問題,錯誤的原因是什麼,這就涉及到了異常的後續處理。
如果你做的應用上架到了微軟應用商店,那麼在微軟應用商店的後台,會記錄你的軟體在用戶處的使用狀況,而當出現異常的時候,也會上傳到你的軟體後台,這樣就方便管理了:
你可以在後台觀察出現的異常,然後在程序里解決它。
但是凡事總有例外,微軟應用商店也不能捕獲所有的異常並加以分析,這裡分享一個例子:
我在開發WFA的時候,遇到過一個棘手的問題,Win10 14393的用戶在打開應用設置時應用會閃退,而更高版本的則不會。當時在應用商店後台查看時,它也不知道原因,顯示一個Unkonwn Exception,這我就很尷尬了啊。
百思不得其解的情況下,我在App.xaml.cs的異常捕獲函數中加了個小東西,即捕獲到異常後,將異常的解釋傳到我的資料庫里。通過這樣的方式,我很快找到了問題的成因,即AutoSuggestBox控制項的某個樣式在14393系統中不支持,這導致應用無法渲染,直接閃退了。
雖然最後我還是放棄了14393的支持(使用了ContentDialog的新控制項),但這種本地處理也可以作為一個經驗保留下來(現在的WFA也沒有在異常捕獲里加上傳代碼了)。
小小總結一下,閃退異常的後續處理可以通過兩種方式來解決:
? 一種是依賴微軟應用商店的異常上傳機制,這種方式便於管理;
? 當前種處理方式不能滿足需求時,可以在App.xaml.cs中的異常捕獲函數里進行本地處理,將更為詳細的信息上傳到你的資料庫中,便於你進行分析。
不過要注意,由於發布的安裝包基本都是Release的,異常捕獲不會有Debug時那樣精準,有時候也需要自己根據情況進行分析。
第二種閃退原因
閃退原因可分為兩部分,一種是我前面講的代碼中出現了未捕獲的異常,而另一種,則是應用渲染無法獲取到對應資源,這一點就尤其顯示出UWP開發平台的不成熟性了。
這種原因說白了其實就是「樣式引起的閃退」,這個在我前面分享的WFA的例子中也提及過。
開發過UWP應用的同學對於控制項樣式應該不陌生吧。這個是UI的關鍵部分。而控制項樣式的設計,低版本(15063及以下)可以使用Blend,而更高版本,Blend尚未支持,就需要自己創建控制項樣式的副本,手動對XAML代碼進行修改(我現在已經更偏向於這一種處理方式了)。
不論是利用Blend還是手動改,都需要創建控制項樣式的副本,這個副本依據什麼創建的呢?依據的是系統默認的樣式。而系統默認的樣式有一個很嚴重的問題,以16299為例。
眾所周知,在16299中,Win10採用了Fluent Design,很多控制項的默認樣式都進行了更新,添加了一種名為AcrylicBrush的筆刷,而在最新的17134中,則有Reveal光效。當這些僅特定版本支持的特殊樣式被內化到系統默認樣式中,一件凄涼的事情就發生了:
一個最為基礎的控制項,你認為的各個版本都會支持的控制項,卻偏偏成了閃退的罪魁禍首。
原因就在於你使用高版本Win10進行開發時,控制項的默認樣式已經不再支持低版本了,而你卻對此並不了解,導致你沒修改控制項的樣式。這樣的應用做出來,雖然名義上支持低版本,但是低版本打開後會因為應用找不到對應的系統資源而無法渲染,因此閃退。
因這種原因而閃退的應用也屢見不鮮,很多時候都是開發者沒有經過認真比對而強行上新的效果造成的。
但是你說這個是開發者的原因嗎?或許是,但微軟也需要承擔一定的責任。你控制項更新就更新吧,好歹告訴我一聲啊,就算沒寫什麼更新說明,那麼在創建默認樣式時,加個波浪線,告訴一聲「該樣式在當前軟體的最低系統版本中不受支持」也好啊。但很可惜的是,目前這種提示文字有,但不全面,仍有一些樣式沒有被包括在提醒列表之內。
所以,當你在App.xaml.cs中完成了對代碼的異常捕獲後,如果應用依然會出現閃退,那麼你就要考慮一下這種樣式原因了。
個人博客地址:blog.richasy.cn


※OneDrive Win10版更新:支持100多種文件
※太漂亮!Windows 10文件Fluent流暢設計
TAG:IT之家 |