ButterKnife能夠說是目前最流行、最受歡迎的輕量級視圖註解框架之一了,博主本身也曾癡迷於這種註解框架,以爲它是最好用的安卓開發工具之一。java
直到有一次接到一個需求,要在Android Studio中開發一個子項目的fragment組件數組
public class SubFragment extends Fragment { @BindView(R.id.view1) View view1; @OnClick(R.id.view1) void onView1Click(View view) { } }
而後悲劇就發生了,@BindView(R.id.view1)提示紅色錯誤"Attribute value must be constant",不能使用,不得不從新使用findViewById來查找名爲「view1」的視圖。app
通過搜索查詢,發現了一個對於ButterKnife及其相似工具的致命問題,即,ButterKnife及其相似工具,是使用視圖的真實id來操做的。框架
在Android Studio的主項目(application)中,R文件中記錄的id是真實的、靜態的、不可變的(static final),能夠經過ButterKnife註解。然而在子項目(library)中,因爲系統特性所限,R文件中記錄的id是非靜態、可變的,會使得ButterKnife生成的代碼產生歧義,所以ButterKnife拒絕自動生成。ide
後來ButterKnife提供了變通方案,使用R2.id.view1來代替R.id.view1。但這個方案被開發者抱怨,稱仍然存在找不到視圖的問題,不是十份可靠。工具
那麼,還有沒有其餘現有的解決方案呢?佈局
AndroidAnnotations,能夠提供與ButterKnife相似功能,優勢是功能強大,支持多種資源和邏輯的注入;但缺點也很明顯,框架自己較重量級,功能設計必須使用EActivity、EFragment或EService等派生類替代現有的原始類,調用的時候必須修改類名(MyActivity加下劃線變成MyActivity_),不加不能用。開發工具
不過,AndroidAnnotations中一個功能引發了博主主意,即AndroidAnnotations可使用資源的名稱來進行注入,而非資源真實id,相似於:this
@ViewById View view1;
框架會直接使用視圖的名稱view1,而非其真實id R.id.view1來查詢視圖。設計
那麼, 有沒有一種既相似於ButterKnife的輕量級資源註解框架,拿來就用不須要作額外修改,又能像AndroidAnnotations那樣使用資源名稱做註解,使得library中也能使用的註解工具?
很遺憾並無找到。那麼與其苦等他人更新代碼,不如本身現編一個。EasyInjection就所以誕生了。
EasyInjection採用與ButterKnife和AndroidAnnotations同樣的註解原理,經過安卓APT來在預編譯階段分析代碼並建立派生類,再在運行時,經過調用派生類來實現資源的查找與注入。
EasyInjection用法與ButterKnife很是相似:
//使用InjectLayout標記Activity @InjectLayout //使用InjectMenu標記Activity的 @InjectMenu public class InjectionActivity extends Activity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); //使用Injection.injectLayout(activity),來將Activity名稱自動轉化爲佈局資源id,InjectionActivity -> R.layout.activity_injection setContentView(Injection.injectLayout(this)); //使用Injection.inject(activity),來將視圖、字符串、圖片等資源注入activity Injection.inject(this); } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); //使用Injection.injectMenu(activity),來將Activity名稱自動轉化爲菜單資源id,InjectionActivity -> R.menu.activity_injection getMenuInflater().inflate(Injection.injectMenu(this), menu); return true; } //使用InjectView標記一個視圖資源,使用資源名稱取得其真實id,text1 -> R.id.text1; @InjectView TextView text1; //使用InjectClick標記一個視圖資源,爲其注入點擊時間 @InjectClick void text2() { Toast.makeText(this, "點擊了Click Me", Toast.LENGTH_SHORT).show(); } //使用InjectTouch標記一個視圖資源,爲其注入觸摸事件 @InjectTouch boolean text3(MotionEvent motionEvent) { Toast.makeText(this, "觸摸了Touch Me", Toast.LENGTH_SHORT).show(); return true; } //使用InjectCheck標記一個CompoundButton視圖資源,爲其注入選中事件 @InjectCheck void text4(boolean isChecked) { Toast.makeText(this, "選中了Check Me - " + isChecked, Toast.LENGTH_SHORT).show(); } //使用InjectGroupCheck標記一個RadioGroup視圖資源,爲其和其內部RadioButton注入單選事件 @InjectGroupCheck void text5(RadioButton radioButton, int position) { Toast.makeText(this, "選中了Radio Check Me " + position, Toast.LENGTH_SHORT).show(); } //使用InjectDrawable標記一個繪圖資源,使用資源名稱取得其真實id,drawable1 -> R.drawable.drawable1 @InjectDrawable Drawable drawable1; //使用InjectStringArray標記一個字符串數組資源,使用其資源名稱取得其真實id,stringArray1 -> R.array.stringArray1 @InjectStringArray String[] stringArray1; }
能夠看到,除了支持標準的視圖資源註解,EasyInjection還支持Activity、Fragment和Dialog的佈局、菜單資源註解。
使用很是簡單,打一個註解標記便可,不須要指定資源真實id,所以徹底不須要再費盡心思考慮如何兼容library。
與AndroidAnnotations相比,EasyInjection更傾向於資源方面的註解,功能雖然稍微少於前者,但使用方便,不須要修改原始類,之前該怎麼調用,使用EasyInjection後仍是怎麼調用。
下一篇會講解EasyInjection特點註解功能的實現原理