EasyInjection,比ButterKnife還要簡單好用的註解框架

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特點註解功能的實現原理

相關文章
相關標籤/搜索