Java的注解(Annotation)相當於一種標記,在程序中加入注解就等於為程序打上某種標記,標記可以加在包,類,屬性,方法,本地變量上。然后你可以寫一個注解處理器去解析處理這些注解(人稱編譯時注解),也可以在程序運行時利用反射得到注解做出相應的處理(人稱運行時注解)。
開發Android程序時,沒完沒了的findViewById, setOnClickListener等等方法,已經讓大多數開發者頭疼不已。好在市面上有所謂的注解框架可以幫助開發者簡化一些過程。比較流行的有butterknife, annotations, xutils, afinal, roboguice等等。今天我們就來對比一下這些注解框架。
ButterKnife框架分析
首先看下Butterknife,來自Jakewharton大神的力作,特點是接入簡單,依賴一個庫就好了。另外在Android Studio上還有提供一個插件,自動生成注解與類屬性。
Butterknife目前支持的注解有: View綁定(Bind),資源綁定(BindBool, BindColor, BindDimen, BindDrawble, BindInt, BindString),事件綁定(OnCheckedChanged, OnClick, OnEditorAction, OnFocusChange, OnItemClick, OnItemLongClick, OnItemSelected, OnLongClick, OnPageChange, OnTextChanged, OnTouch)。
AndroidAnnotations框架分析
再來分析下著名的Annotations框架。該框架的原理跟Butterknife一樣,都是在編譯時生成代碼,不過annotations並不是生成代碼供對應的類調用去給帶注解的變量、方法賦值,而是直接生成一個繼承帶注解的類,這個類里面有對變量賦值,對注解方法調用的代碼。運行時,直接運行的是annotations生成的類,而不是我們寫的類
方法調用鏈:onCreate(Bundle saveInstanceState) ----> setContentView() ----> onViewChangedNotifier_.notifyViewChanged(),而onViewChanagedNotifier_.notifyViewChanged()方法最終會調用onViewChanged(HasViews hasViews)方法,在此方法中有對變量賦值,事件方法設置的代碼,注意看自動生成的類的名字,發現規律了吧,就是我們寫的類的名字后面加上一個'_'符號,現在知道為什么用Annotations框架,我們的AndroidManifest.xml中對Activity 的配置,Activity的名字要多加一個'_'符號了吧。因為真正加載的是AndroidAnnotations生成的代碼。寫到這里大家發現沒,annotations框架里面一個反射都沒有,沒錯這個框架沒有用到反射,沒有初始化,所有的工作在編譯時都做了,不會對我們的程序造成任何速度上的影響。
那Annotations支持哪些注解呢?既然Annotations性能上跟Butterknife差不多,那功能呢?在這里翻譯一下官網的Features.
1、依賴注入:注入views, extras, 系統服務,資源,...
2、簡化線程模式:在方法上添加注釋來制定該方法是運行在UI線程還是子線程。
3、事件綁定:在方法上添加注釋來制定該方法處理那些views的那個事件。
4、REST client:創建一個client的接口,AndroidAnnotations會生成實現代碼,這是關於網絡方面的。
5、清晰明了:AndroidAnnotations會在編譯時自動生成對應子類,我們可以查看相應的子類來了解程序是怎么運行的。
XUtils框架分析
xutils框架是我們現在在用的框架,那我們就來分析一下他的注解功能。xutils的使用方式跟Butterknife一樣,都是在成員變量,方法上添加注釋,然后調用一個方法(xutils是ViewUtils.inject()方法)對成員變量賦值、事件方法設置到view上。不同的是,Butterknife是調用自動生成的代碼來賦值,而xutils是通過反射來實現的。
可以看到反射、反射到處在反射,雖然現在的反射速度也很快了,但是還是不能跟原生代碼相比,一旦注釋用的多了,這初始化速度會越來越慢。通過上面注釋處理的代碼可以看出,xutils支持的注釋目前主要有UI, 資源,事件,SharedPreference綁定。跟xutils一樣是運行時利用反射去解析注釋的框架還有afinal, roboguice等。
市面上還有很多其他的注釋框架,但是萬變不離其宗,不是反射就是自動生成代碼。反射功能雖然強大,但是不可取,不僅會拖慢速度還會破話程序的封裝性。個人認為生成代碼的方案比較好,所有的功能都在編譯時做了,並不會影響到用戶的體驗,唯一的缺點就是比反射難實現,不過我們程序不就是把難處留給自己,把快樂留給用戶么!
最后,對上面三種框架總結一下。