善用 Annotation 降低犯錯率
留點提示給未來維護的人,降低翻車率
Android 專案裡頭的資源,無論是 String、Drawable 或是放在 Raw 裡頭的檔案,都會被 aapt 工具產生一個 id 作為對應,並存在 R Class 裡頭。例如開發者想存取字串資源,在 Java/Kotlin 程式碼之中透過 R.string.someid
,在 XML 之中透過 @string/someid
就可以取得該字串。
這些 id 的資料型態都是 Int,在一個 Method 傳入一個資源 id ,在該 Method 參數的部分即是需要傳入 Int,這類的 Method 通常需要注意未來使用的人 可能 誤用而傳入一般的整數。當然 Method Name 好好想應該可以避免這類的問題,真不愧是寫程式最大難題。
但除了好好想名字以外,Android Support Library (Android X) 提供了 Annotation Library。在程式碼之中存取了 Annotation 註釋過的變數,Android Studio 會跳出相關的提示,像是提醒這個變數需要 String 資源、這個資源不能為空⋯ 等等,你應該會在很多第三方 Library 之中發現他們都有引用這個 Library。
例如上方的範例,呼叫 showToast(context, @StringRes stringResId)
時, stringResId: Int
傳入 5566,IDE 就會跳出紅字提醒。
在開始以前,需要在 Gradle 之中加入新的 dependency (擇一):
dependencies {
// If you stay on Support Library
implementation 'com.android.support:support-annotations:28.0.0' // If you use AndroidX
implementation 'androidx.annotation:annotation:1.0.1'
}
常用範例簡介
Nullable/NonNull
上次提到 Java 如何跟 Kotlin 更好的協作,有提到這兩個 Annotations。這兩個 Annotations 的功能是提示目前的變數有沒有可能是 null,可以與 Kotlin 的 Null safety 檢查功能互相配合。
就算只使用 Java 本身,編寫程式時也可以透過 IDE 的提示獲得提醒,也可以透過文件知道這個參數本身能不能傳 null 進去。
例如上圖的狀況,最好做個 null check 比較保險。
另外指定了 NonNull,未來使用上如果傳入 null,IDE 也會給出相關的提示。
另外,部分開發者 Migrate 到 AndroidX Library 後,會發現 Android Studio 的 Nullable 提示消失了,其實可以透過手動將它開啟回來。
先開啟 Preferences,到 Editor → Inspections 頁面 (搜尋 Inspections 更快),找到 Java → Probable bugs → @NonNull/@Nullable Problems
(搜尋 nullable 更快),右方的 Options 拉到底打開 Configure Annotations。
將 Android X 的 Nullable 和 NonNull 加入 Annotations 選項裡頭,加入後別忘了還要按下勾勾,看見藍色箭頭指向 andoridx.annotation
這個 package 的 Class 即可。
IntRange/FloatRange
這幾個 Annotation 用來提示變數可接受傳入的大小,可以檢查最大值與最小值 (或其中一個)。IntRange 用來檢查整數,FloatRange 用來檢查浮點數,size 則是用來檢查 Collection 或 Array 的大小。
例如這個的程式碼:
透過 @IntRange(from = min, to = max)
來檢查傳入值,from 和 to 可以只寫一個,只檢查最大值或是最小值。 刻意輸入負數, IDE 就會提醒這個數字必須大於或等於 1。
FloatRange 的用法與這個無異,也是決定最大值、最小值後判斷是否在這個區間之內。
IdRes/LayoutRes/DrawableRes/ …[Any]Res
這些與最初提到的 StringRes 相似,都是為了判斷傳入的 id 是不是相對應的某個類別的資源。第一個 IdRes 是 Layout 上 View 的 id,其他的應該都能從開頭的字大概看出這個 ID 是什麼資源的 ID。
這裡用 idRes 做為例子,做一個 Extension Function 讓 Activity 可以 Lazy initialize 指定的 View。
嘗試丟數字進去,Android Studio 會跳出警告。
其他的 Resource Check Annotation 用法大致上也都是雷同。
遇到錯誤時可以參考 IDE 跳出來的提示: Expected resource of type [here]
看出需要的是哪種資源類型。
RequirePermission
Android 6.0 (Marshmallow, APIv 23) 之後,一些系統資源需要取得使用者的授權才能正常存取,否則可能會發生 Crash。例如相機、位置的權限,開發者在使用這類的 Method 時需要檢查使用者是否已授權。
以位置的權限為例,你可以自行做一個開始監聽 Location 變化的 Method。但在 Method 裡頭不判斷權限的取得狀態,反而拋至需要存取這個 Method 時,再由需要存取地方做判斷。 (有點像把 Exception throw 出去)
如果需要多個權限,可以寫在 @RequirePermission(allOf = Array<String>)
,allOf 這個 String Array 之中。
補充資料
除了以上介紹這些比較常用的以外,還可以去 Android Developer 查查文件有多詳細的介紹。
希望這些 Annotation 能夠提升之後維護時的開發體驗 (尤其是幾個月後的自己),減少誤用 Method 的機會。 👨🏻🔬