一、前言
ButterKnife 项目地址: https://github.com/JakeWharton/butterknife
ButterKnife是一个专注于Android系统的View注入框架,对性能基本没有损耗,因为ButterKnife用到的注解并不是在运行时反射的,而是编译时生成的新class。
优势:
- 强大的View绑定和click事件处理功能,简化代码,提高开发效率
- 方便处理Adapter里的ViewHolder绑定问题
- 运行是不会影响App效率,使用配置方便
- 代码清晰,可读性强
二、基本配置
步骤
- 在Project的build gradle中添加如下代码:
buildscript {
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
classpath 'com.jakewharton:butterknife-gradle-plugin:9.0.0-rc1'
}
}
- 在App的build gradle中添加如下代码:
- 根节点添加:
apply plugin: 'com.jakewharton.butterknife'
- dependencies中添加:
implementation 'com.jakewharton:butterknife:9.0.0-rc1'
annotationProcessor 'com.jakewharton:butterknife-compiler:9.0.0-rc1'
三、注册与绑定
1.Activity中绑定
绑定Activity必须在setContentView之后,使用ButterKinfe.bind(this)进行绑定,可以写在BaseActivity中完成绑定。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
}
2.Fragment中绑定
在onCreateView进行绑定,使用ButterKinfe.bind(this,view)方法,返回Unbinder实例,在onDestroyView中调用Unbinder的unbind()方法解绑。
public class ButterKnifeFragment extends Fragment {
private Unbinder unbinder;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_butter_knife, container, false);
//返回一个Unbinder值(进行解绑),注意这里的this不能使用getActivity()
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onDestroyView() {
super.onDestroyView();
//进行解绑操作
unbinder.unbind();
}
}
3.adapter中进行绑定
在ViewHolder加一个构造器,在new ViewHolder的时候吧view传递过去,使用ButterKnife.bind(this,view)进行绑定:
class ViewHolder {
@BindView(R2.id.tv_butter_knife_2)
TextView tvButterKnife2;
@BindView(R2.id.but_butter_knife_2)
Button butButterKnife2;
ViewHolder(View view) {
ButterKnife.bind(this, view);
}
}
// recyclerview.viewHolder
class MyHolder extends RecyclerView.ViewHolder {
@BindView(R2.id.tv_butter_knife_2)
TextView tvButterKnife2;
@BindView(R2.id.but_butter_knife_2)
Button butButterKnife2;
public MyHolder(@NonNull View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
四、基本使用
1.绑定view
- 控件id注解:@BindView()
@BindView(R2.id.button)
Button button;
- 布局内多个控件id注解:@BindViews()
@BindViews({R2.id.but_test, R2.id.but_test2})
List
2.绑定资源
- 绑定string字符串:@BindString()
@BindString(R.string.test)
String strTest;
- 绑定string里面array数组:@BindArray()
@BindArray(R.array.city)
String[] citys;
- 绑定Bitmap资源:@BindBitmap()
@BindBitmap(R.mipmap.ic_launcher)
Bitmap bitmap;
- 绑定颜色值:@BindColor()
@BindColor(R2.color.colorAccent)
int colorAccent;
3.绑定事件
- 绑定点击事件:@OnClick()
@OnClick(R.id.but_test)
public void showToast() {
Toast.makeText(this, "test", Toast.LENGTH_SHORT).show();
}
@OnClick(R.id.but_test)
public void onClick(View view){
//TODO something
}
@OnClick(R.id.but_test)
public void onClick(Button button){
//TODO something
}
- 绑定长按点击事件:@OnLongClick()
@OnLongClick(R.id.but_test)
public void onShowToast(){
Toast.makeText(this, "test", Toast.LENGTH_SHORT).show();
}
- 指定多个id绑定事件 (此时必须使用R,使用R2只能分开写)
@OnClick({R.id.but_test, R.id.but_test2})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.but_test:
Toast.makeText(this, "点击test", Toast.LENGTH_SHORT).show();
break;
case R.id.but_test2:
Toast.makeText(this, "点击test2", Toast.LENGTH_SHORT).show();
break;
}
}
-Listener中的多方法注解
如果对应的监听器有多个回调,可通过注解绑定任何一个,每一个注解都有一个它绑定的默认回调。通过指定参数替换回调。
spinner原生写法:
private void initSpinner(){
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView> parent, View view, int position, long id) {
//TODO
}
@Override
public void onNothingSelected(AdapterView> parent) {
//TODO
}
});
}
通过Butter Knife 注解方法
@OnItemSelected(R.id.spinner_city)
public void onItemSelected(){
// TODO
}
@OnItemSelected(value = R.id.spinner_city,callback = OnItemSelected.Callback.NOTHING_SELECTED)
public void onNothingSelected(){
// TODO
}
注意事项
8.0.0之前的Bind标签在8.0.0之后变成了BindView,而8.7.0之后在绑定view时,要用R2.id.XXX而不再是常用的R.id.XXX了。
附录
绑定注解
注解 | 作用 | 使用 |
---|---|---|
@BindView | 绑定一个view | @BindView(R2.id.test) TextView textview; |
@BindViews | 绑定多个view | @BindViews({R2.id.test1,R2.id.test2}) List |
@BindArray | 绑定string里面array数组 | @BindArray(R.array.city) String[] citys; |
@BindBitmap | 绑定图片资源Bitmap | @BindBitmap(R.mipmap.ic_launcher) Bitmap bitmap; |
@BindBool | 绑定boolean值 | |
@BindColor | 绑定color | @BindColor(R.color.colorAccent)int collorAccent; |
@BindDimen | 绑定Dimen | @BindDimen(R.dimen.borth_width)int borderWidth; |
@BindDrawable | 绑定Drawable | @BindDrawable(R.drawable.test_pic) Drawable testPic |
@BindFloat | 绑定float | |
@BindInt | 绑定int | |
@BindString | 绑定一个String id 为一个String变量 | @BindString(R.string.app_name)String appName |
事件注解
注解 | 作用 |
---|---|
@OnClick | 点击事件 |
@OnCheckedChanged | 选中,取消选中 |
@OnEditorAction | 软键盘功能键 |
@OnFocusChange | 焦点改变 |
@OnItemClick item | 被点击(注意这里有坑,如果item里面有Button等这些有点击的控件事件的,需要设置这些控件属性focusable为false) |
@OnItemLongClick item | 长按(返回真可以拦截onItemClick) |
@OnItemSelected | item被选择事件 |
@OnLongClick | 长按事件 |
@OnPageChange | 页面改变事件 |
@OnTextChanged | EditText里面的文字变化事件 |
@OnTouch | 触摸事件 |
@Optional | 选择性注入,如果当前对象不存在,就会抛出一个异常,为了压制这个异常,可以在变量或者方法上加入一下注解,让注入变成选择性的,如果目标View存在,则注入, 不存在,则什么事情都不做 |
代码混淆
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
@butterknife.* ;
}
-keepclasseswithmembernames class * {
@butterknife.* ;
}
插件 zelezny
将光标移到setContentView(R.layout.acty_login),将光标放到R.layout.acty_login,然后右键Generate,选择GenerateBUtterKnife Injections