要成为一名优秀的Android开发者,除了丰富的项目经验外,还需要有一份完备的知识体系,在这里我们一起成长一起学习,让自己成为理想中的自己~
在平常的Android开发中,是否会经常觉得当Layout中的控件比较多的时候要写一堆的findViewById()效率低下?是否觉得经常通过各种setxxxListener来设置事件监听很繁琐?那么ButterKnife就是解决以上问题的
public class MainActivity extends BaseActivity<MainContract.Presenter> implements MainContract.View {
@BindView(R.id.test_tv)
TextView testTv;
@BindView(R.id.test_btn)
Button testBtn;
Unbinder unbinder;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.test_layout);
unbinder = ButterKnife.bind(this, view);
}
@OnClick({R.id.test_tv,R.id.test_btn})
protected void handleViewClick(View view){
switch(view.getId()){
case R.id.test_tv:
Log.d("TEST","tsest tv click");
break;
case R.id.test_btn:
Log.d("TEST","tsest btn click");
break;
}
}
@Override
protected void onDestory(){
super.onDestory();
if (unbinder != null && unbinder != Unbinder.EMPTY) {
unbinder.unbind();
unbinder = null;
}
}
}
看到如上代码是不是觉得简洁很多了呀
通过示例代码可以看出,之前我们都是通过findViewById()的方法了找到xml布局中的View,这里我们使用了@BindView()的注解方式替代了。然后使用了@OnClick()替代了之前的setOnClickListener()方法。当然ButterKnife类似的方法还有很多,我们后续会逐一介绍。
ButterKnife的初期版本是通过使用注解+反射这样的运行时解析的方式实现上述功能的,之后为了改善性能,便使用了注解+APT编译时解析技术并从中生成配套模板代码的方式来实现。所以在开始使用之前,我们先简单的了解下什么是APT。
APT是Annotation Processing Tool的缩写,即注解处理工具。
它的使用步骤一般是这样的:
激动人心的时候到了,现在我们来学习怎么用ButterKnife
首先,需要在module的build.gradle中,添加如下:
android {
...
// Butterknife requires Java 8.
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'com.jakewharton:butterknife:10.2.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.1'
}
首先要将ButterKnife与Activity、Fragment或者View先进行绑定。由于每次在Activity或者Fragment中进行绑定,所以这里建议将bind的操作写到BaseActivity或BaseFragment中,这样之后都继承他们,就不用再重复的写bind代码了
注意:绑定Activity必须在setContentView之后
public abstract class BaseActivity extends Activity {
private Unbinder unbinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getContentView());
unbinder = ButterKnife.bind(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (unbinder != null && unbinder != Unbinder.EMPTY) {
unbinder.unbind();
unbinder = null;
}
}
protected abstract int getContentView();
}
在8.4版本开始ButterKnife移除了ButterKnife.unBind()方法,当时取而代之的是ButterKnife.bind(this)会返回一个Unbinder的引用,通过Unbinder的unbind()方法进行解除绑定。
// 这里的修饰类不能是private或者static,否则会报异常: @BindView fields must not be private or static.
@BindView(R.id.test_tv)
protected TextView testTv;
@BindViews({R.id.test_tv,R.id.test_tv2})
protected List<TextView> testTvs;
@BindString(R.string.test_str)
protected String mTestStr;
@BindArray(R.array.test_str_array)
protected String[] testStrArray;
@BindBitmap(R.mipmap.ic_launcher)
protected Bitmap bitmap;
注意:这类事件绑定的可以不用声明View,直接注解在方法上进行绑定
单个View的点击事件绑定
@OnClick(R.id.test_tv)
protected void handleViewClick(){
Log.d("TEST","test tv click");
}
多个View的点击事件
@OnClick({R.id.test_tv,R.id.test_tv2})
protected void handleMoreViewClick(View view){
int viewId = view.getId();
switch(viewId){
case R.id.test_tv:
Log.d("TEST","test tv click");
break;
case R.id.test_tv2:
Log.d("TEST","test tv2 click");
break;
}
}
@OnTextChanged(value = R.id.mobileEditText, callback = OnTextChanged.Callback.BEFORE_TEXT_CHANGED)
void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@OnTextChanged(value = R.id.mobileEditText, callback = OnTextChanged.Callback.TEXT_CHANGED)
void onTextChanged(CharSequence s, int start, int before, int count) {
}
@OnTextChanged(value = R.id.mobileEditText, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
void afterTextChanged(Editable s) {
}
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
@butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
@butterknife.* <methods>;
}
最后这里做个小小的总结
1、ButterKnife.bind()的调用在Activity中必须在setContentView之后
2、声明修饰符不能用private和static,否则会抛异常
3、建议封装一个自己的BaseActivity或BaseFragment来统一调用ButterKnife.bind()方法,子类继承后则可不用再进行绑定
4、在8.4之后版本移除了unBInd方法,使用ButterKnife.bind(this)返回一个Unbinder的引用,通过Unbinder的unbind()方法来进行解绑
最后完成后,在Review下自己的代码是不是觉得清晰了很多呢?
什么?还是觉得麻烦?有没有更好的办法呢?还可以更懒吗?别急下一篇我们来聊聊怎么用插件生成以上代码!