Butterknife是一个Android的注解框架,可以代替findViewById和onClick等方法,达到精简代码的目的。
1、 官网介绍及下载jar包
http://jakewharton.github.io/butterknife/
2、 导入butterknife框架
把jar包导入工程里面,并且在Activity里面使用注解的方式来绑定控件:
public class MainActivity extends ActionBarActivity {
@InjectView(R.id.main_text_1) TextView tv_1;
@InjectView(R.id.main_text_2) TextView tv_2;
@InjectView(R.id.main_text_3) TextView tv_3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
init();
}
private void init() {
tv_1.setText("第一行");
tv_2.setText("第二行");
tv_3.setText("第三行");
}
}直接这样使用是不行的,会报空指针异常,还要配置Eclipse。官网介绍配置方法:
http://jakewharton.github.io/butterknife/ide-eclipse.html
具体的配置方法如下:
右键工程----> propertise----> java compiler ----> Annotation Processing ----> 勾选Enable projectspecific settings
然后打开AnnotationProcessing ----> Factory Path ----> Add JARs,把下载的jar包添加进来
然后工程才能正常运行,跟普通的jar包使用起来不一样,那么如果我们导入别人的工程是使用了butterknife框架的,能不能正常运行和修改呢?继续试验:
使用butterknife框架的工程比其他工程多了这样一个文件夹:
点击进去是一个java文件,用来执行查找view的操作:
MainActivity$$ViewInjector.java:
package com.butterknifetest;
import android.view.View;
import butterknife.ButterKnife.Finder;
public class MainActivity$$ViewInjector {
public static void inject(Finder finder, final com.butterknifetest.MainActivity target, Object source) {
View view;
view = finder.findRequiredView(source, 2131034173, "field 'tv_1'");
target.tv_1 = (android.widget.TextView) view;
view = finder.findRequiredView(source, 2131034175, "field 'tv_3'");
target.tv_3 = (android.widget.TextView) view;
view = finder.findRequiredView(source, 2131034172, "field 'helloWorldTextView'");
target.helloWorldTextView = (android.widget.TextView) view;
view = finder.findRequiredView(source, 2131034174, "field 'tv_2'");
target.tv_2 = (android.widget.TextView) view;
}
public static void reset(com.butterknifetest.MainActivity target) {
target.tv_1 = null;
target.tv_3 = null;
target.helloWorldTextView = null;
target.tv_2 = null;
}
}
把Eclipse里面原来的工程删掉,再重新导入,程序能正常运行,但是再用这种注解的方式绑定新的控件,就会出现空指针异常,要按照前面的方法重新配置Eclipse,多人合作开发或者导入别人使用了这个框架的工程时要注意。
3、继续研究butterknife能用在程序的哪些地方,实现精简代码:
① 可以在Activity、fragment和Adapter的ViewHolder里面使用,取代findViewById方法
Activity:
public class MainActivity extends ActionBarActivity {
@InjectView(R.id.main_text_1) TextView tv_1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
tv_1.setText("第一页");
}
}
Fragment:
在fragment的onCreateView里注入时,应该在onDestroyView里设置视图为空:
public class FancyFragment extends Fragment {
@InjectView(R.id.button1) Button button1;
@InjectView(R.id.button2) Button button2;
@Override View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fancy_fragment, container, false);
ButterKnife.inject(this, view);
// TODO Use "injected" views...
return view;
}
@Override void onDestroyView() {
super.onDestroyView();
ButterKnife.reset(this);
}
}
Adapter:
public class MyAdapter extends BaseAdapter {
@Override public View getView(int position, View view, ViewGroup parent) {
ViewHolder holder;
if (view != null) {
holder = (ViewHolder) view.getTag();
} else {
view = inflater.inflate(R.layout.whatever, parent, false);
holder = new ViewHolder(view);
view.setTag(holder);
}
holder.name.setText("John Doe");
// etc...
return view;
}
static class ViewHolder {
@InjectView(R.id.title) TextView name;
@InjectView(R.id.job_title) TextView jobTitle;
public ViewHolder(View view) {
ButterKnife.inject(this, view);
}
}
② 可以使用@InjectViews获取view列表,如:
@InjectViews({ R.id.main_text_1, R.id.main_text_2, R.id.main_text_3 })
List<TextView> nameViews;
然后可以通过apply方法定义view列表中所有view的行为:
ButterKnife.apply(nameViews, DISABLE);
ButterKnife.apply(nameViews, ENABLED, true);
static final Action<View> DISABLE = new Action<View>() {
@Override public void apply(View view, int index) {
((TextView)view).setText("第一行");
}
};
static final Setter<View, Boolean> ENABLED = new Setter<View, Boolean>() {
@Override public void set(View view, Boolean value, int index) {
if(value) {
((TextView)view).setText("true");
} else {
((TextView)view).setText("false");
}
}
};
③ 点击监听注入
直接通过id来监听点击事件:
@OnClick(R.id.main_text_1)
public void tv_1() {
Toast.makeText(MainActivity.this, "点击了第一行", 2000).show();
}
还可以把view作为参数传入方法:
@OnClick(R.id.main_text_2)
public void tv_2(TextView tv) {
tv.setTextSize(20);
Toast.makeText(MainActivity.this, "点击了第二行", 2000).show();
}
还可以同时传入多个id:
@OnClick({ R.id.main_text_1, R.id.main_text_2, R.id.main_text_3 })
public void pickDoor(TextView tv) {
switch (tv.getId()) {
case R.id.main_text_1:
Toast.makeText(MainActivity.this, "点击了第一行", 2000).show();
break;
case R.id.main_text_2:
Toast.makeText(MainActivity.this, "点击了第二行", 2000).show();
break;
case R.id.main_text_3:
Toast.makeText(MainActivity.this, "点击了第三行", 2000).show();
break;
default:
break;
}
}
简单介绍到这里,更加具体的用法,可以去查看官网~