天天看点

ButterKnifey学习笔记

ButterKnifey的GitHub地址为https://github.com/JakeWharton/butterknife/

配置参考GitHub地址,如下:

在你的project的build.gradle中配置android-apt插件,内容如下:

buildscript {
  repositories {
    mavenCentral()
   }
  dependencies {
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
  }
}
           

然后再你的module中应用你刚刚添加的插件,内容如下:

apply plugin: 'com.neenbedankt.android-apt'
android {
  ...
}
dependencies {
  compile 'com.jakewharton:butterknife:8.4.0'
  apt 'com.jakewharton:butterknife-compiler:8.4.0'
}
           

Library projects

如果你要在你的库项目中使用ButterKnifey,请在你的buildscript 中添加插件:

buildscript {
  repositories {
    mavenCentral()
   }
  dependencies {
    classpath 'com.jakewharton:butterknife-gradle-plugin:8.4.0'
  }
}
           

然后在你的module中应用插件:

apply plugin: 'com.android.library'
apply plugin: 'com.jakewharton.butterknife'
           

然后,现在请在所有的ButterKnifey的声明中,用R2代替R,如:

class ExampleActivity extends Activity {
  @BindView(R2.id.user) EditText username;
  @BindView(R2.id.pass) EditText password;
...
}
           

常用功能:

1、使用@BindView代替findViewById(ButterKnife v6.1.0之前是使用@InjectView) ,如:

可以这样实现:

@BindView(R.id.butter_text_view_1)
TextView mTextView1;
           

如果id找不到,会在编译的时候报错的。

Activity:

通常,我们在设置好布局之后调用ButterKnife.bind(this);,即必须在setContentView();之后,且父类bind绑定后,子类不需要再bind,如

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.demo_butter_knife);

    //using butter knife
    ButterKnife.inject(this);
}
           

注意,需要在onDestroy()时解绑:

@Override  
    protected void onDestroy() {  
        super.onDestroy();  
        ButterKnife.unbind(this);//解除绑定,官方文档只对fragment做了解绑  
    }  
           

Fragment:

与Activity不同的是,Fragment中需要传入一个View,ButterKnife.bind(this, mRootView); 如:

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_simple, container, false);
        ButterKnife.bind(this, view);
        return view;
    }
           

注意,需要在onDestroyView() 时解绑:

@Override  
    public void onDestroyView() {  
        super.onDestroyView();  
        ButterKnife.unbind(this);//解绑  
    }  
           

需要注意的是View变量声明的时候不能为private或者static.

还可以用来简化Adapter里面的ViewHolder: 具体参考https://github.com/gindoc/AndroidButterKnifeSample/blob/master/app/src/main/java/com/example/mengdd/butterknifesample/data/PersonAdapter.java

,如:

public class TestAdapter extends BaseAdapter {  
    private List<String> list;  
    private Context context;  

    public TestAdapter(Context context, List<String> list) {  
        this.list = list;  
        this.context = context;  
    }  

    @Override  
    public int getCount() {  
        return list==null ?  : list.size();  
    }  

    @Override  
    public Object getItem(int position) {  
        return list.get(position);  
    }  

    @Override  
    public long getItemId(int position) {  
        return position;  
    }  

    @Override  
    public View getView(int position, View convertView, ViewGroup parent) {  
        ViewHolder holder;  
        if (convertView == null) {  
            convertView = LayoutInflater.from(context).inflate(R.layout.layout_list_item, null);  
            holder = new ViewHolder(convertView);  
            convertView.setTag(holder);  
        } else {  
            holder = (ViewHolder) convertView.getTag();  
        }  
        holder.textview.setText("item=====" + position);  
        return convertView;  
    }  

    static class ViewHolder {  
        @Bind(R.id.hello_world)  
        TextView textview;  

        public ViewHolder(View view) {  
            ButterKnife.bind(this, view);  
        }  
    }  
}  
           

2、绑定资源,如

@BindString(R.string.app_name)  
String appName;//sting  
@BindColor(R.color.red)  
int textColor;//颜色  
@BindDrawable(R.mipmap.ic_launcher)  
Drawable drawable;//drawble  
@Bind(R.id.imageview)  
ImageView mImageView;  
@Bind(R.id.checkbox)  
CheckBox mCheckBox;  
@BindDrawable(R.drawable.selector_image)  
Drawable selector;  
           

3、绑定点击事件,监听方法的参数是可选的,如:

  • v直接绑定一个方法(有参)
@OnClick(R.id.submit)  
public void submit(View view) {  
  // TODO submit data to server...  
} 
           
  • 直接绑定一个方法(无参)
@OnClick(R.id.submit)  
public void submit() {  
  // TODO submit data to server...  
}  
           
  • 参数是一个特定的类型,它将自动被转换
@OnClick(R.id.submit)  
public void sayHi(Button button) {  
  button.setText("Hello!");  
} 
           
  • 多个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();  
  }  
}  
           
  • 自定义view可以绑定自己的监听,不指定id
public class FancyButton extends Button {  
  @OnClick  
  public void onClick() {  
    // TODO do something!  
  }  
}  
           
  • 添加多回调方法的监听的使用方法,如 给EditText加addTextChangedListener,利用callback指定回调方法,实现想回调的方法即可,(哪个注解不会用点进去看下源码)
@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) {  

}  
           

方法注解可以用来绑定到这些方法中的任何一个.

每一个注解有一个默认的callback,指定它绑定到什么方法上;可以通过callback参数指定为一个特定的方法.

比如,(此处用Spinner的onItemSelectedListener举例):

mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {
    }
});
           

没有指定callback,默认对应onItemSelected()方法:

@OnItemSelected(R.id.my_spinner)
    //default callback : ITEM_SELECTED
void onItemSelected(int position) {
    Toast.makeText(this, "position: " + position, Toast.LENGTH_SHORT).show();
}
           

指定了callback,对应onNothingSelected()方法:

@OnItemSelected(value = R.id.my_spinner, callback = OnItemSelected.Callback.NOTHING_SELECTED)
void onNothingSelected() {
    Toast.makeText(this, "Nothing", Toast.LENGTH_SHORT).show();
}
           
  • 对一组View进行统一操作

a.装入一个list,如

@Bind({ R.id.first_name, R.id.middle_name, R.id.last_name })  
List<EditText> nameViews;  
           

b.设置统一处理

static final ButterKnife.Action<View> DISABLE = new ButterKnife.Action<View>() {  
  @Override public void apply(View view, int index) {  
    view.setEnabled(false);  
  }  
};  
static final ButterKnife.Setter<View, Boolean> ENABLED = new ButterKnife.Setter<View, Boolean>() {  
  @Override public void set(View view, Boolean value, int index) {  
    view.setEnabled(value);  
  }  
}; 
           

c.统一操作处理,例如设置是否可点,属性等

ButterKnife.apply(nameViews, DISABLE);  
ButterKnife.apply(nameViews, ENABLED, false);
           

apply()方法允许你为一组对象批量地设置值.

apply()方法共有3种形式:

public static <T extends View> void apply(List<T> list, Action<? super T> action)
public static <T extends View, V> void apply(List<T> list, Setter<? super T, V> setter, V value)
public static <T extends View, V> void apply(List<T> list, Property<? super T, V> setter, V value)
           

即Action, Setter和Property三种.

其中Action和Setter都是ButterKnife的类,需要继承,写自己的子类实现,然后传入对象.

Setter的第三个参数可以指定要set到什么值.

Property是Android中的类:https://developer.android.com/reference/android/util/Property.html

具体的使用可以参见例子:https://github.com/gindoc/AndroidButterKnifeSample/blob/master/app/src/main/java/com/example/mengdd/butterknifesample/ViewListActivity.java

  • 可选绑定:默认情况下,“绑定”和“监听”绑定都是必需的。如果不能找到目标视图,则将抛出异常。所以做空处理
@Nullable @Bind(R.id.might_not_be_there) TextView mightNotBeThere;  

@Nullable @OnClick(R.id.maybe_missing) void onMaybeMissingClicked() {  
  // TODO ...  
}  
           

之前的版本v6.1.0用的是@Optional?

选择性注入(Optional Injection):

默认情况下,@InjectView和listener的注入都是必须的,如果target view没有被发现,则会报错.

为了抑制这种行为,可以用@Optional注解来标记field和方法,让注入变成选择性的,如果targetView存在,则注入, 不存在,则什么事情都不做.

当布局被复用时,这个@Optional注解很有用.

代码混淆

-keep class butterknife.** { *; }  
-dontwarn butterknife.internal.**  
-keep class **$$ViewBinder { *; }  

-keepclasseswithmembernames class * {  
    @butterknife.* <fields>;  
}  

-keepclasseswithmembernames class * {  
    @butterknife.* <methods>;  
}  
           

Zelezny插件的使用

在AndroidStudio->File->Settings->Plugins->搜索Zelezny下载添加就行,如图:

ButterKnifey学习笔记

安装好后需要restart你的Android Studio。

在使用此插件前,需要已经导入了butterknife的jar(或者在build.gradle中已经加入:compile’com.jakewharton:butterknife:7.0.0’)

随后,在你需要导入注解的Activity或者Fragment或者ViewHolder的layout资源代码上,右击,选择 Generate 然后Generate ButterKnife Injections,这时候生成类似于下列的选择框:

ButterKnifey学习笔记

Element为view的类型,ID为layout中资源的id名字,Variable Name即为你在代码中引用出来的变量名,点击Confirm后即可。

下面是Android ButterKnife Zelezny的github上的一个动态使用流程图:

ButterKnifey学习笔记

以上例子,fork自https://github.com/mengdd/AndroidButterKnifeSample

以上文章参考:

http://blog.csdn.net/itjianghuxiaoxiong/article/details/50177549

http://www.cnblogs.com/mengdd/p/4595973.html

http://www.cnblogs.com/soaringEveryday/p/4607438.html?utm_source=tuicool&utm_medium=referral

继续阅读