一般來說,annotation 可以在 compile time 或是 runtime 的時候做處理。
在這兩者各有優缺點,annotation processor 雖然可以在 runtime 的時候直接進行 parse ,省下不少讀取 annotation 和爬結構的時間,但缺點就是 compile 的時候會比較久。相反地,runtime 透過 proxy 或 reflection 的方式去爬資料,雖然不用花 compile 的時間,但 runtime 會花時間處理 annotation 和資料結構。之前在實作的時候,我們有做實驗,也有權衡了一下這兩者之前的優劣,後來選擇了 annotation processor ,因為 podcast 滿多的格式檔案都滿大的,而且 tag 多種又複雜,靠 runtime 處理實在是會花很多時間在處理結構,Android 開發常用的 gson 和 Retrofit 就是在 runtime 處理 annotation 。
// Retrofit
interface GitHubService {
@GET("users/{user}/repos")
suspend fun listRepos(@Path("user") user: String)
}
另一個有趣的是,如果你是 Android 的開發者應該對於 dagger 這個 library 不陌生,他們有提供一些 annotation 讓使用者來自訂一些東西,像是 @Inject
、 @Component
或者 @Provides
之類的,這背後就是在 compile time 就已經決定好要幫你產生哪些 dependency injection 會用的 class 。而我們的目標就是要可以做到類似的效果,透過自定義的 annotation 去產生對應的 parser ,讓我們不用自己寫程式碼,也可以達到自定義資料格式和 parser 的效果。
// Dagger
@Provides
fun provideUserRepository(): UserRepository {
return UserRepository()
}