【原创】Android Butterknife 的分析与使用
Android Butterknife 的分析与使用
0. 内容概览
-
1. 问题背景
-
2. Butterknife简介
-
3. Butterknife的使用方法
-
4. Butterknife的使用范例
-
4. Butterknife的使用注意事项
-
5. 总结
- 6. 参考文档
1. 问题背景
在项目的开发过程中,发现当前有两个小问题:
-
Activity代码可读性较差;
-
需要手动填写大量的View绑定,Click事件绑定,ViewHolder事件绑定等,影响开发效率。
2. Butterknife简介
ButterKnife是一个专注于Android系统的View注入框架,可以减少大量的findViewById以及setOnClickListener代码,可视化一键生成。
使用ButterKnife框架可以很好地解决问题上述问题。
3. Butterknife的使用方法
3.1. 本地插件下载
在settings搜索Zelezny,如下所示:
3.2. 本地框架搭建
(1) Project的build.gradle中添加依赖
dependencies {
classpath 'com.android.tools.build:gradle:2.0.0'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
(2) app的build.gradle中增加classpath内容
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.jakewharton:butterknife:8.1.0'
apt 'com.jakewharton:butterknife-compiler:8.1.0'//增加这一句
}
(3) 在Activity基类中进行注解的绑定与解绑,如下:
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做了解绑 } }
其他Activity继承至BaseActivity即可正常使用Butterknife插件。
(4) 在Fragment中基类中对Butterknife进行绑定和解绑,如下:
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);//解绑 } }
其他Fragment继承至BaseFragment即可正常使用Butterknife插件。
3.3. 可视化一键生成注解
对于要进行注解的layout文件,通过快捷键一键添加Butterknife注解,如下所示:
自动补全代码如下:
然后通过注解生成的textView,imageView就可以正常使用了。
3.4. 手动注解
(1) 绑定View(以Button为例):
@BindView( R.id.button ) private Button button;
(2) 绑定String:
@BindString( R.string.msg ) private String msg;
(3) 绑定String数组
@BindArray(R.array.citys ) private String [] citys ;
(4) 绑定Bitmap资源
@BindBitmap( R.mipmap.wifi ) private Bitmap wifi_bitmap ;
(5) 绑定颜色值
@BindColor( R.color.black ) private int black ;
(6) 绑定OnClick事件
@OnClick(R.id.button )
private void click(){ Toast.makeText(this, "is a click", Toast.LENGTH_SHORT).show(); }
(7) 绑定OnLongClick事件
@OnLongClick( R.id.button1 ) //给 button1 设置一个长按事件
private void longClick(){Toast.makeText(this, "is a long click", Toast.LENGTH_SHORT).show();}
其他方法以此类推,所有的绑定注释如下所示:
4. Butterknife的使用范例
(1) 一般Activity
使用前
public class ExampleActivity extends AppCompatActivity {
private final static String TAG = ExampleActivity.class.getSimpleName();
String butterKnifeStr;
Drawable butterKnifeDrawable;
Button butterKnifeBtn;
ImageView butterKnifeIv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_butter_knife);
initResource();
initViews();
}
private void initViews() {
butterKnifeBtn = (Button) findViewById(R.id.btn_butter_knife);
butterKnifeBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "onButterKnifeBtnClick");
}
});
butterKnifeIv = (ImageView) findViewById(R.id.iv_butter_knife);
butterKnifeBtn.setText(butterKnifeStr);
butterKnifeIv.setImageDrawable(butterKnifeDrawable);
}
private void initResource() {
butterKnifeStr = getString(R.string.title_btn_butter_knife);
butterKnifeDrawable = getDrawable(R.mipmap.ic_launcher);
}
}
使用后:
public class ButterKnifeActivity extends AppCompatActivity {
private final static String TAG = ButterKnifeActivity.class.getSimpleName();
private Unbinder unbinder;
@BindString(R.string.title_btn_butter_knife)
String butterKnifeStr;
@BindDrawable(R.mipmap.ic_launcher)
Drawable butterKnifeDrawable;
@BindView(R.id.btn_butter_knife)
Button butterKnifeBtn;
@BindView(R.id.iv_butter_knife)
ImageView butterKnifeIv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_butter_knife);
unbinder = ButterKnife.bind(this);
initViews();
}
private void initViews() {
butterKnifeBtn.setText(butterKnifeStr);
butterKnifeIv.setImageDrawable(butterKnifeDrawable);
}
@OnClick(R.id.btn_butter_knife)
public void onButterKnifeBtnClick(View view) {
Log.e(TAG, "onButterKnifeBtnClick");
}
@Override
protected void onDestroy() {
super.onDestroy();
unbinder.unbind();
}
}
(2) Adapter的使用
使用前
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.person_item_layout, null);
holder = new ViewHolder();
holder.name = (TextView) convertView.findViewById(R.id.name);
holder.age = (TextView) convertView.findViewById(R.id.age);
holder.location = (TextView) convertView.findViewById(R.id.location);
holder.work = (TextView) convertView.findViewById(R.id.work);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Person person = getItem(position);
if (null != person) {
holder.name.setText(person.getName());
holder.age.setText(String.valueOf(person.getAge()));
holder.location.setText(person.getLocation());
holder.work.setText(person.getWork());
}
return convertView;
}
static class ViewHolder {
TextView name;
TextView age;
TextView location;
TextView work;
}
使用后
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.person_item_layout, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Person person = getItem(position);
if (null != person) {
holder.name.setText(person.getName());
holder.age.setText(String.valueOf(person.getAge()));
holder.location.setText(person.getLocation());
holder.work.setText(person.getWork());
}
return convertView;
}
static class ViewHolder {
@InjectView(R.id.person_name)
TextView name;
@InjectView(R.id.person_age)
TextView age;
@InjectView(R.id.person_location)
TextView location;
@InjectView(R.id.person_work)
TextView work;
public ViewHolder(View view) {
ButterKnife.inject(this, view);
}
}
可以发现,使用Butterknife后,不仅可以通过注解节省大量的写代码的时间,而且可以增强代码的可读性。
5. Butterknife的使用注意事项
-
本地搭建Butterknife框架,通过gralde下载Android studio的相关依赖文件,可以通过链接下载相关jar包等资源文件,并将依赖文件覆盖到C:\Users\(***)\.gradle\caches\modules-2目录下,可以节省更新gradle的时间;
-
Activity或者Fragment中使用ButterKnife,要注意在onCreate中绑定,在onDestroy中解绑,否则可能会造成内存泄漏
-
ButterKnife只能在标注为Application的Module中使用;
-
Activity ButterKnife.bind(this);必须在setContentView();之后,且父类bind绑定后,子类不需要再bind;
-
Fragment ButterKnife.bind(this, mRootView);
-
属性布局不能用private or static 修饰,否则会报错
5. 总结
总的来说,ButterKnife有以下几点优势:
-
-
兼容之前的使用,所以不会对之前的使用方法造成影响
-
强大的View绑定和Click事件处理功能,简化代码,提升开发效率
-
方便的处理Adapter里的ViewHolder绑定问题
-
运行时不会影响APP效率,使用配置方便
-
代码清晰,可读性强
-
6. 参考文献
-
http://jakewharton.github.io/butterknife/
-
http://www.cnblogs.com/zhaoyanjun/p/6016341.html
-
http://www.jianshu.com/p/9ad21e548b69
-
https://github.com/JakeWharton/butterknife
-
http://blog.csdn.net/itjianghuxiaoxiong/article/details/50177549
-
http://www.jianshu.com/p/0392199a682b
-
http://www.cnblogs.com/flyme/p/4517560.html