Field and method binding for Android views which uses annotation processing to generate boilerplate code for you.
- Eliminate findViewById calls by using @BindView on fields.
- Group multiple views in a list or array. Operate on all of them at once with actions, setters, or properties.
- Eliminate anonymous inner-classes for listeners by annotating methods with @OnClick and others.
- Eliminate resource lookups by using resource annotations on fields.
這是摘自大神@JakeWharton的Github-ButterKnife上的介紹祝懂〖偶危總所周知,有了這它,媽媽再也不用擔(dān)心我寫無聊的findViewById()和setOnClickListener()等代碼了弦赖,可謂是安卓開發(fā)之必備喳挑。
Remember: A butter knife is like a dagger only infinitely less sharp.
1. 如何使用
- Gradle 中引入 ButterKnife 框架:
dependencies {
compile 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
}
在library中使用ButterKnife
添加插件到library的buildscript中
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.jakewharton:butterknife-gradle-plugin:8.8.1'
}
}
然后在使用該library的module中,配置以下插件
apply plugin: 'com.android.library'
apply plugin: 'com.jakewharton.butterknife'
- 對于Activiry掀抹,由于每次都要在Activity中的onCreate綁定Activity虐拓,所以寫一個BaseActivity完成綁定是一個不錯的選擇,子類繼承即可
注:ButterKnife.bind(this)傲武;綁定Activity 必須在setContentView之后
public abstract class BaseActivity extends Activity {
public abstract int getContentViewId();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getContentViewId());
ButterKnife.bind(this);
initAllMembersView(savedInstanceState);
}
protected abstract void initAllMembersView(Bundle savedInstanceState);
@Override
protected void onDestroy() {
super.onDestroy();
ButterKnife.unbind(this);
}
}
- 綁定fragment
public abstract class BaseFragment extends Fragment {
public abstract int getContentViewId();
protected Context context;
protected View mRootView;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mRootView =inflater.inflate(getContentViewId(),container,false);
ButterKnife.bind(this,mRootView);//綁定framgent
this.context = getActivity();
initAllMembersView(savedInstanceState);
return mRootView;
}
protected abstract void initAllMembersView(Bundle savedInstanceState);
@Override
public void onDestroyView() {
super.onDestroyView();
ButterKnife.unbind(this);//解綁
}
}
- 控件id 注解: @BindView()
public class ButterknifeActivity extends AppCompatActivity {
@BindView( R.id.button1 )
public Button button1 ;
// 注意:button 的修飾類型不能是:private 或者 static 蓉驹。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_butterknife);
//綁定activity
ButterKnife.bind( this ) ;
button1.setText( "I am a button ");
}
}
- 點擊事件的綁定:不用聲明view,不用setOnClickLisener()就可以綁定點擊事件
5.1 直接綁定一個方法
@OnClick(R.id.submit)
public void submit(View view) {
// TODO submit data to server...
}
5.2 所有監(jiān)聽方法的參數(shù)是可選的
@OnClick(R.id.submit)
public void submit() {
// TODO submit data to server...
}
5.3 定義一個特定類型谱轨,它將自動被轉(zhuǎn)換
@OnClick(R.id.submit)
public void sayHi(Button button) {
button.setText("Hello!");
}
2. ButterKnife原理
ButterKnife的實現(xiàn)并不是基于反射而實現(xiàn)的戒幔,它用了Java Annotation Processing技術(shù)。
APT(Annotation processing tool)是一種處理注釋的工具土童,它對源代碼文件進行檢測找出其中的Annotation诗茎,使用Annotation進行額外的處理。
Annotation處理器在處理Annotation時可以根據(jù)源文件中的Annotation生成額外的源文件和其它的文件(文件具體內(nèi)容由Annotation處理器的編寫者決定)献汗,APT還會編譯生成的源文件和原來的源文件敢订,將它們一起生成class文件。
使用APT主要的目的是簡化開發(fā)者的工作量罢吃,因為APT可以編譯程序源代碼的同時楚午,生成一些附屬文件(比如源文件,類文件尿招,程序發(fā)布描述文件等)矾柜,這些附屬文件的內(nèi)容也都是與源代碼相關(guān)的阱驾,換句話說,使用APT可以代替?zhèn)鹘y(tǒng)的對代碼信息和附屬文件的維護工作怪蔑。
Butterknife用的APT(Annotation Processing Tool)編譯時解析技術(shù)(現(xiàn)在已經(jīng)改成了谷歌的更強大的annotationProcessor里覆,APT已經(jīng)停止更新了)。大概原理就是你聲明的注解的生命周期為CLASS,然后繼承AbstractProcessor類缆瓣。繼承這個類后喧枷,在編譯的時候,編譯器會掃描所有帶有你要處理的注解的類弓坞,然后再調(diào)用AbstractProcessor的process方法隧甚,對注解進行處理,那么我們就可以在處理的時候渡冻,動態(tài)生成綁定事件或者控件的java代碼戚扳,然后在運行的時候,直接調(diào)用方法完成綁定菩帝。
當(dāng)你編譯你的Android工程時咖城,ButterKnife工程中ButterKnifeProcessor類的process()方法會執(zhí)行以下操作:
- 開始它會掃描Java代碼中所有的ButterKnife注解@Bind、@OnClick呼奢、@OnItemClicked等;
- 當(dāng)它發(fā)現(xiàn)一個類中含有任何一個注解時宜雀,ButterKnifeProcessor會幫你生成一個Java類,名字類似$$ViewBinder握础,這個新生成的類實現(xiàn)了ViewBinder接口 ;
- 這個ViewBinder類中包含了所有對應(yīng)的代碼辐董,比如@Bind注解對應(yīng)findViewById(), @OnClick對應(yīng)了view.setOnClickListener()等等 ;
最后當(dāng)Activity啟動ButterKnife.bind(this)執(zhí)行時,ButterKnife會去加載對應(yīng)的ViewBinder類調(diào)用它們的bind()方法禀综。