Android中提取表單模型

lum發表於2014-07-10

我一直追求從Android活動中分離程式碼。在最近的一個專案中,我成功的實現了傳統的”Form Model”模式,想在此分享我的感想。

“Form Model”的基本思想是,把處理UI互動以及資料繫結和狀態保持的程式碼提取到單獨的類中。這種分離非常自然,並且讓我們的Activity變得簡單。

我認為在Android中這個領域不太被關注——在大多數的開發文件中資料錄入和表單不是重點。在很多流行的社交應用程式中,大多數的畫面只是顯示資訊;可能也有幾個畫面用於發微博或者訊息,但不是應用的痛點。

對我來說,上兩個Android應用有特別多的資料錄入工作。部分原因是因為所處的領域(醫療、金融)和客戶(更貼近於企業應用而不是創業)。但我們經常把“表單輸入”介面搞得一片混亂——特別是當開始新增東西的時候,比如編輯現有的條目,提示丟棄未儲存的更改,以及處理旋轉而不會清除所有欄位值。

使用這種表單模型方案會減少bug,讓程式碼更容易理解,開發者也會變得更快樂。

搜尋表單示例

我們有一個銀行應用程式,希望有一個畫面來搜尋交易資料。有多個過濾條件:開始是一個金額下拉選單,一個關鍵字欄位和一個金額範圍。(希望你可以想象在未來將會增加更多的這類過濾器,複雜性會激增)。

我們沒有把所有的檢視、單擊處理程式,驗證邏輯和資料繫結的程式碼堆到一個Activity中,而是要建立一個 SearchForm類來處理這一切。

我們建立了一個類,繼承自LinearLayout(或者FrameLayout,由你的喜好決定)。它允許把相關的控制元件組織到一個佈局中,我們將填充佈局,設定列表檢視併為金額列表建立一個介面卡。

我們把Android控制元件封裝到getter和setter方法中​——這可能會有些爭議,但我認為它使SearchForm擁有更好的公共API。我們有一個方法來驗證使用者的輸入,並根據需要提供錯誤資訊。 buildParameters()方法做了一些資料繫結工作並返回業務物件。結尾的兩個方法使用了Android onSaveInstanceState中的Bundle,以處理自定義配置的更改(注意,大多數的原始UI控制元件會自行處理持久化)。

這是個一百行左右的程式碼,大部分還不錯。這個類中所有內容似乎都屬於“搜尋表單”物件,對未來的特性有良好的功能擴充套件點(日期範圍過濾器、支出與存款過濾器、只用支票等)。我們有意避免處理如何獲取資料,把它留給了其他更適合的地方處理這些邏輯程式碼。

活動中的程式碼是什麼樣的呢?

我們的Activity在XML佈局檔案中包含了一個 **標籤,並且只處理高層面的使用者互動(點選動作欄中的提交按鈕),並協調獲取和儲存資料。繁重的UI控制和表單邏輯都委託給了 **SearchForm

Activity的程式碼在50行左右——其中大部分是處理框架中生命週期和選單建立的樣板程式碼。

總體印象

一旦涉及到API或資料庫,事情總是會變得更復雜。但總體來講,通過把表單特定的邏輯和檢視相關內容移出活動,程式碼變得更容易理解。

我可以為 SearchForm編寫大量的Robolectric測試程式碼而且不會帶來與活動生命週期有關的問題。我可以為表單的互動、動作欄、後端編寫測試程式碼而不用考慮邊界。當為表單新增新過濾條件時,可以避免對活動做任何的更改(類似於設計模式中的開/閉原則)。

對比其他框架(從其他開發人員的角度來說),Android中資料繫結功能很弱。這種設計似乎還差點什麼,因為和Android的類耦合的過於緊密,依賴於方法的呼叫順序(initialize()方法應在validate()方法之前呼叫)——儘管如此,但我認為對於“所有內容混在一起的Activity”來說是一種改進。

隨著表單模型越來越複雜,你可能要考慮把驗證邏輯提取到一個單獨的物件中,並且把自定義檢視功能移動到自己的控制元件中(就像我們例子中的 CurrencyEditText)。此外,為了更好的為使用者服務,也可以考慮把複雜的表單拆分成為多步驟嚮導。

我們發現這種模式可以成功的清理亂糟糟的表單程式碼,建議嘗試一下。我把程式碼模式稍微規範了一下,並建立了一個小的基類,以減少樣板程式碼,可以隨意的使用


我希望聽到您的想法、意見或建議,請在Twitter上和我聯絡。

相關文章