ButterKnife使用详解

简介

正如其官网所说:"Field and method binding for Android views",ButterKnife是对Android view的属性和方法的强大的绑定注解框架。
GitHub地址:https://github.com/JakeWharton/butterknife/
官网地址:http://jakewharton.github.io/butterknife/
它能节省很多代码量,像findViewById这种代码就不用再出现了,而且这个框架也提供了很多其他有用的注解,可以大大的提升开发效率!

配置

现在最新版本为butterknife:8.4.0
在Gradle中添加依赖:

compile 'com.jakewharton:butterknife:8.4.0'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'

使用

①在Activity中使用

我们需要在声明变量的时候添加注解:

@BindView(R.id.text)
TextView textView;
@BindView(R.id.button)
Button button;

之后在setContentView()之后调用:

ButterKnife.bind(this);

声明的控件就可以使用了!
这里需要注意的问题:
1. Activity中ButterKnife.bind(this);必须在setContentView();之后调用,且父类bind绑定后,子类不需要再bind,所以我们一般可以把它写在BaseActivity中!
2. 声明的属性不能用private或者static修饰,否则会报错!

②在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); 
        // TODO Use fields... 
        return view; 
    } 
}

在重载的bind()方法中,传入根布局即可!

③在Adapter中使用

Adapter有一种常用的优化策略,就是使用ViewHolder来减少findViewById()的重复调用。

@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 {
        @BindView(R.id.person_name)
        TextView name;
        @BindView(R.id.person_age)
        TextView age;
        @BindView(R.id.person_location)
        TextView location;
        @BindView(R.id.person_work)
        TextView work;

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

ButterKnife.bind()方法可以被放在任何你想使用findViewById的地方。

提供的其他绑定API:
1. 使用Activity在任意对象中进行绑定。如果你使用了类似MVC的编程模式,你可以使用ButterKnife.bind(this, activity)在Controller中进行绑定
2. 使用ButterKnife.bind(this)绑定一个布局的子布局到变量上。如果你在布局中使用了<merge>标签并且在自定义的控件构造时inflate这个布局,你可以在inflate之后立即调用它。或者,你可以在onFinishInflate()回调中使用它。

④绑定资源

绑定资源到属性上可以使用@BindBool@BindColor@BindDimen@BindDrawable@BindInt@BindString。使用时对应的注解需要传入对应的id资源,例如@BindString你需要传入R.string.id_string的字符串的资源id。

class ExampleActivity extends Activity {
  @BindString(R.string.title) String title;
  @BindDrawable(R.drawable.graphic) Drawable graphic;
  @BindColor(R.color.red) int red; // int or ColorStateList field
  @BindDimen(R.dimen.spacer) Float spacer; // int (for pixel size) or float (for exact value) field
  // ...
}

⑤View List,绑定多个view

我们可以使用@BindViews把多个view放在集合或数组中进行绑定:

@BindViews({R.id.edit1,R.id.edit2,R.id.edit3})//里边要有大括号
List<EditText> editTexts;

注意:id用逗号分隔,大括号包围,外面才是小括号.
使用这种绑定时,你可以使用apply()函数。该函数相当于将在这个列表中每一个元素上进行调用,为一组对象批量地设置值.
apply()有三种重载方法:

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)

其中ActionSetter是ButterKnife中的两个接口:

public interface Action<T extends View>{
    @UiThread
    void apply(@NonNull T view, int index);
}
public interface Setter<T extends View, V>{
    @UiThread
    void set(@NonNull T view, V value, int index);
}

在使用的时候需要我们自行实现这两个接口,然后传入对象。Setter的第三个参数是指定要set什么值!
Property是Android中的类,它包含view的一些基本属性,比如透明度,平移,缩放,旋转等。可以这样使用:

ButterKnife.apply(editTexts, View.ALPHA, 0.0f);

⑥绑定监听事件

@OnClick(R.id.button)
void test(View view){
    Toast.makeText(this,"点击事件",Toast.LENGTH_SHORT).show();
}

注意:这里方法仍然不能是private和static, 并且可以有一个参数View,也可不写.并且写的时候可以直接写一个具体的子类,比如参数View可以写成Button,这里的cast是自动完成的.
除了点击事件@OnClick,还有ListView的点击@OnItemClick, CheckBox的@OnCheckedChanged等等.
另外可以一次指定多个id,为多个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!
  }
}

⑦绑定重置

可以用undind()方法将ButterKnife注入的View引用设置为null.
比如在Fragment的onCreateView()里调用ButterKnife.bind()方法注入了一些View,这个方法会返回一个Unbinder 对象,在onDestroyView()里想把它们置为null,可以直接调用unbinder.undind(this);方法.

⑧可选的绑定

在默认情况下, @BindView和监听器的绑定都是需要目标view的,如果目标view没有找到的话,Butter Knife将会抛出一个异常。
如果你并不想接收到这样的信息,那么就在你的方法或变量上使用@Nullable或者@optional吧。

@Nullable @BindView(R.id.might_not_be_there) TextView mightNotBeThere;

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

⑧多方法的Listener

有一些View的listener是有多个回调方法的,比如Spinner的onItemSelectedListener,它有两个回调方法:
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
public void onNothingSelected(AdapterView<?> parent)
方法注解可以用来绑定到这些方法中的任何一个.
每一个注解有一个默认的callback,指定它绑定到什么方法上;可以通过callback参数指定为一个特定的方法.

@OnItemSelected(R.id.spinner) 
void onItemSelected(int position) { 
    // TODO ... 
}
@OnItemSelected(value = R.id.spinner, callback = OnItemSelected.Callback.NOTHING_SELECTED) 
void onNothingSelected() { 
    // TODO ... 
}

需要注意的是Spinner中只要有数据,默认都会选中第0个数据,所以想进入到onNothingSelected()方法,就需要把Adapter中的数据都清空.

⑨更加简单的findViewById

ButterKnife.findById()可以用来获取Activity,Dialog或View中的任何View.
ButterKnife自动完成了类型转换,所以获取出来以后不用进行显式强转,直接赋值给具体的View类型引用即可.

总结

以上就是ButterKnife全部的比较常用的使用方法!
想要了解它的实现原理的,当然是要看源码啦!推荐一下下面的两篇文章,可以参考一下:
深入理解ButterKnife源码并掌握原理(一)
这是一个系列的文章,讲解的比较详细,涉及的内容也比较多!最后还有自己根据原理写的一个相似的demo,可以看一下!

ButterKnife源码剖析

参考文章:
ButterKnife基本使用
ButterKnife使用详解
Android Butter Knife 框架——最好用的View注入

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值