天天看點

《Android應用開發攻略》——2.2 異常處理

ian darwin

2.2.1 問題

java有一個精心定義的異常處理機制,但是需要花費一定的時間學習,才能高效地使用而不至于使使用者或者技術支援人員感到沮喪。

2.2.2 解決方案

java提供了一個exception層次結構,正确地使用它能夠帶來相當大的靈活性。android提供了包括對話框和toast的多種機制,用于通知使用者錯誤的情況。android開發者應該熟悉這些機制,并學習高效使用它們的方法。

2.2.3 讨論

java從推出時就有兩類異常(實際上是exception類的父類throwable):檢測型(checked)異常和非檢測型(unchecked)異常。在java标準版中,程式設計人員明顯要面對這樣一個事實:在編譯的時候可以檢測到某些情況,但其他的情況則無法檢測。例如,如果許多pc上安裝一個桌面應用程式,可能有些pc上的磁盤空間已經很緊張,無法儲存資料;與此同時,其他pc上應用程式依賴的一些檔案可能由于使用者的錯誤(而非程式設計人員的錯誤)、偶發事件、老鼠咬斷電纜等情況而丢失。是以,ioexception被當作“檢查型異常”,意味着程式設計人員必須檢查這類異常,檢查可以通過檔案使用方法中的try-catch子句或者方法定義中的throws子句來完成。所有經過良好訓練的java開發人員都知道如下的通用規則:

throwble是可抛出異常層次結構的根。exception及其子類(runtimeexception(及其子類)除外)都是檢測型異常。其他異常為非檢測型異常。

上述規則意味着,error及其所有子類都是非檢測異常(見圖2-1)。例如,如果你收到一個vmerror異常,說明出現了一個運作時bug,作為應用程式程式設計人員,對此你沒有什麼可做的。runtimeexception子類包含了名稱超長的arrayindexoutofboundsexception等異常,它和它的友元都是非檢測型異常,因為在開發時測試及捕捉這些異常是你的責任(參見第3章)。

《Android應用開發攻略》——2.2 異常處理

捕捉異常的場所

早期對檢測型異常的(過度)使用導緻許多早期java開發人員編寫的代碼中到處都是try/catch代碼塊,部分原因是:在早期的一些教育訓練項目和書籍中,對throws子句的使用沒有得到足夠的重視。随着java本身越來越多地轉向企業應用,較新的架構(如hibernate和spring)出現并強調非檢測型異常的使用,這類問題才得到改正。現在,盡可能捕捉靠近使用者的異常這一理念已經得到普遍的接受。準備(在程式庫或者多個應用程式中)重用的代碼不應該嘗試錯誤處理,它們所能做的是所謂“異常轉譯”(exception translation),也就是說,将與技術相關的(通常是檢查型)異常轉換為通用的非檢測型異常。例2-1展示了基本的模式。

例2-1:異常轉譯

注意,即便在這個代碼中,檢測型異常的用法也很零亂:is.close()實際上不可能失敗,但是因為将它放在finally塊中(如果檔案打開但是出現了某種錯誤,這樣可以確定檔案關閉),就必須使用另一個try-catch結構。是以,檢測型異常(很可能)是不好的,在新的api中應該避免使用它,在必要時應該用非檢測型異常來掃清道路。

oracle官方網站和其他人則支援相反的看法。在本書網站上的一條評論中,al sutton提出了如下看法:

檢測型異常迫使開發人員承認錯誤的情況可能發生,他們必須思考處理錯誤的方式。在許多情況下,除了日志和恢複可能沒有太多的事情可做,但是開發人員仍然考慮到此類錯誤發生的時候所應采取的措施。這個例子說明阻止方法調用者區分檔案不存在(因而沒有必要重新讀取)和檔案讀取問題(檔案存在但是無法讀取)這兩種不同錯誤情況之間的差別。

android忠于javaapi,有許多檢測型異常(包括例子中說明的那些),是以對這些異常應該以相同的方式處理。

對異常的處理

應用程式應該始終報告異常。當我看到捕捉的異常卻不采取任何措施的代碼時,我總會感到絕望。但是,異常隻應該報告一次(不要既進行記錄,又轉譯/重新抛出異常)。普通異常的重點是表示異常情況(正如名稱所表示的那樣)。因為在android裝置上沒有系統管理者或者控制台操作員,是以必須向使用者報告異常情況。

你應該考慮通過一個對話框或者toast通知報告異常。移動裝置上的異常處理與桌上型電腦有所不同。使用者可能正在開車(或者操作其他機器),與人交談,是以你不應該猜測他們的注意力都在應用程式上。記住,toast通知隻在螢幕上出現幾秒鐘,你可能會錯過它。如果使用者必須采取行動更正錯誤,就應該使用對話框。我知道大部分的示例(甚至在本書中也是一樣)使用toast,這是因為toast通知需要的代碼比對話框少(相反,blackberry api簡化了對話框:dialog.alert("mes sage"))。toast簡單地彈出,然後消失。對話框則要求使用者确認異常情況,或者授權應用程式執行某些付費操作(例如,啟動網際網路通路,以便運作需要下載下傳地圖資料的應用程式)。

注意: 使用toast來“彈出”不重要的資訊,而使用對話框顯示重要的資訊并得到确認。

繼續閱讀