Android Butterknife

wongstar發表於2017-11-29

開發中找到xml中對應的ui並設定對應的事件,一般用findViewById,然後設定onClick事件來實現,這樣寫起來比較麻煩,有沒更簡單的?Butterknife本場的主角閃亮登場.
Butterknife作用:
通過註解的方式來對Android View進行繫結.

Butterknife的Github原始碼如下:
github.com/JakeWharton…
對它的介紹可以看下面連結:
jakewharton.github.io/butterknife…

下面根據文件描述,簡單的介紹下如何使用:

註解例項變數view 取代findViewById
class ExampleActivity extends Activity {
@BindView(R.id.title)
TextView title;//取代findViewByid(R.id.title)
@BindView(R.id.subtitle)
TextView subtitle;//取代findViewByid(R.id.subtitle)
@BindView(R.id.footer)
TextView footer;//取代findViewByid(R.id.footer)

@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_activity);
ButterKnife.bind(this);//注意這裡必須設定繫結當前Activity
// TODO Use fields...
//後續就可以直接使用比如
title.setText("Just test");
}
}
上面程式碼在butterknife內部生產類似下面的code

public void bind(ExampleActivity activity) {
activity.subtitle = (android.widget.TextView) activity.findViewById(2130968578);
activity.footer = (android.widget.TextView) activity.findViewById(2130968579);
activity.title = (android.widget.TextView) activity.findViewById(2130968577);
}
對資源繫結註解
在Butterknife中定義如下對資源的註解
@BindBool, @BindColor, @BindDimen, @BindDrawable, @BindInt, @BindString 上面的可以對應獲取android res目錄下對應的資源。
舉個?:
class ExampleActivity extends Activity {
@BindString(R.string.title)
String title;
@BindDrawable(R.drawable.graphic)
Drawable graphic;
@BindColor(R.color.red)
int red; // int or ColorStateList field
@BindDimen(R.dimen.spacer)
Float spacer; // int (for pixel size) or float (for exact value) field
// ...
}
不在Activity中如何使用butterknife
bind對應的view通過它們的root view,舉個例子在Fragment中
public class FancyFragment extends Fragment {
@BindView(R.id.button1) Button button1;
@BindView(R.id.button2) Button button2;

@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fancy_fragment, container, false);
ButterKnife.bind(this, view);//注意這裡傳入的是root view
// TODO Use fields...
return view;
}
}
或者是在ViewHolder中使用

static class ViewHolder {
@BindView(R.id.title) TextView name;
@BindView(R.id.job_title) TextView jobTitle;

public ViewHolder(View view) {
  ButterKnife.bind(this, view);//這裡對應的是bind(this,view)
}複製程式碼

}
繫結View List
@BindViews({ R.id.first_name, R.id.middle_name, R.id.last_name })
List nameViews;
繫結View的事件
對應View onClick事件
@OnClick(R.id.submit)
public void submit(View view) {//其中submit方法中的引數是可選的
// TODO submit data to server...
}
對應ViewOnItemSelected事件

@OnItemSelected(R.id.list_view)
void onItemSelected(int position) {
// TODO ...
}
當然也可以多個view對應一個click事件如下:

@OnClick({ R.id.door1, R.id.door2, R.id.door3 })
public void pickDoor(DoorView door) {
if (door.hasPrizeBehind()) {
Toast.makeText(this, "You win!", LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Try again", LENGTH_SHORT).show();
}
}
在自定義View的繫結事件更簡單如下:

public class FancyButton extends Button {
@OnClick
public void onClick() {
// TODO do something!
}
}
釋放對應的bind資源
public class FancyFragment extends Fragment {
@BindView(R.id.button1) Button button1;
@BindView(R.id.button2) Button button2;
private Unbinder unbinder;//全域性變數

@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fancy_fragment, container, false);
unbinder = ButterKnife.bind(this, view);
// TODO Use fields...
return view;
}

@Override public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();//在onDestoryView中釋放對應的資源
}
}
其他較為少用的方法
TextView firstName = ButterKnife.findById(view, R.id.first_name);
//替換findViewById 不需要強轉
//The apply method allows you to act on all the views in a list at once
ButterKnife.apply(nameViews, DISABLE); //馬上設定
ButterKnife.apply(nameViews, ENABLED, false);//設定
遇到版本問題,具體如下
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LogUtil.d("onCreate........................");
myLocationListener = new MyLocationListener(getLifecycle());
setContentView(R.layout.lifecycle_test);
ButterKnife.bind(this);
}

@OnClick(R.id.btnJump)
public void onClick(View view){
    Intent intent = new Intent(this, DatabaseStudyActivity.class);
    startActivity(intent);
}複製程式碼

發現點選Button無法響應對應的onClick時間,什麼原因呢?google了下發現是build.grandle配置出現了問題,下面是build.gradle中的配置

implementation 'com.jakewharton:butterknife:8.8.1'
implementation 'com.jakewharton:butterknife-annotations:8.8.1'複製程式碼

ButterKnife從7.x到8.x後,執行時和編譯器被分開來了,所以需要加入compiler在build.grandle中,如下所示:

annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
這樣整個build.gradle配置如下:

implementation 'com.jakewharton:butterknife:8.8.1'
implementation 'com.jakewharton:butterknife-annotations:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'複製程式碼

相關文章