对于我来说多写几个findview没什么,最起码有利于定位空指针问题,但是还是了解了一下这个注解框架。
官网地址是:http://jakewharton.github.io/butterknife/
1.添加依赖::
app下的build.gradle
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.jakewharton:butterknife:8.5.1'//添加这里
annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'//添加这里
}
项目下的build.gradle
dependencies {
classpath 'com.android.tools.build:gradle:3.2.0-beta01'
classpath 'com.jakewharton:butterknife-gradle-plugin:8.5.1'//添加这里
}
2.使用:
@BindView(R.id.tv_main)
TextView tv_main;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
}
@OnClick(R.id.tv_main)
public void show(){
Toast.makeText(this,"butterKnife点击",Toast.LENGTH_SHORT).show();
}
绑定多个控件:
@BindViews({ R.id.first_name, R.id.middle_name, R.id.last_name })
List<EditText> nameViews;
资源绑定:
通过预定义的注解(@BindBool, @BindColor, @BindDimen, @BindDrawable, @BindInt, @BindString)结合一个资源 ID以和表示该资源类型的相应的字段。
class ExampleActivity extends Activity {
@BindString(R.string.title) String title;
@BindDrawable(R.drawable.graphic) Drawable graphic;
@BindColor(R.color.red) int red;
@BindDimen(R.dimen.spacer) Float spacer;
// ...
}
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);
return view;
}
}
List适配器中的用法:
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("测试");
return view;
}
static class ViewHolder {
@BindView(R.id.title) TextView name;
@BindView(R.id.job_title) TextView jobTitle;
public ViewHolder(View view) {
ButterKnife.bind(this, view);
}
}
}
多个监听器绑定:
@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();
}
}
重置绑定:
Fragment的生命周期与Activity不同,当我们在onCreateView绑定Fragment,在onDestroyView将View 设置为null时,Butter Knife 的 unbind()方法可以帮我们做这些。
public class FancyFragment extends Fragment {
Unbinder mUnbinder ;
@Bind(R.id.button1) Button button1;
@Bind(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);
mUnbinder = ButterKnife.bind(this, view);
return view;
}
@Override public void onDestroyView() {
super.onDestroyView();
mUnbinder .unbind();
}
}
代码混淆
在代码混淆的时候可能出问题,这时候需要在当前model下的proguard-rules.pro文件做如下修改:
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
@butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
@butterknife.* <methods>;
}
3.注意事项
(1).在Activity类中绑定,必须在setContentView()之后绑定,且父类bind绑定后,子类不需要在bind。
(2).在Fragment,ViewHold中绑定:ButterKnife.bind(this,view);这里的this不能替换成getActivity()。
(3).在Activity中不需要做解绑操作,在Fragment中必须在onDestroyView()中做解绑操作。
(4).使用ButterKnife修饰的方法和控件,不能用private or static 修饰,否则会报错。
(5).setContentView()不能通过注解实现。(其他的有些注解框架可以)。
(6).在异步请求中,我们常常会更新UI,这个时候如果页面销毁了,ButterKnife也解绑了,那么就会报空指针异常,
所以必须在异步回调里来判断是否已经解绑;方法是在unbind()之后将mUnbinder=null
在异步回调时,首先判断mUnbinder==null,则return;