ButterKnife配置与使用

ButterKnife是我很欣赏的国外大神JakeWharton的作品,是一个专注于Android系统的View注入框架,可以减少大量的findViewById以及setOnClickListener代码,通过Android Studio 插件可以可视化一键生成。

下面是Readme所述 的功能
- Eliminate findViewById calls by using @BindView on fields.
- Group multiple views in a list or array. Operate on all of them at once with actions, setters, or properties.
- Eliminate anonymous inner-classes for listeners by annotating methods with @OnClick and others.
- Eliminate resource lookups by using resource annotations on fields.

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


dependencies {
  compile 'com.jakewharton:butterknife:8.5.1'
    apt 'com.jakewharton:butterknife-compiler:8.5.1'
}

同时也要在buile.gradle(project)中配置依赖。

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

然后就可以在代码中使用butterKnife了

绑定View

@BindView(R.id.toolbar)
    Toolbar tb_toolbar;
    @BindView(R.id.toolbar_layout)
    CollapsingToolbarLayout ct_toolbarLayout;
    @BindView(R.id.app_bar)
    AppBarLayout ab_appBar;
    @BindView(R.id.content_main)
    NestedScrollView ns_contentMain;

绑定资源文件

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
  // ...
}

Fragment绑定view

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;
  }
}

ViewHolder

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("John Doe");
    // etc...

    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);
    }
  }
}

生成相同类型的View集合,并统一控制他们的属性

通过Action和Setter接口定义一个控件简单的行为,然后将这个行为应用到一组控件中。

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);
  }
};
@BindViews({ R.id.first_name, R.id.middle_name, R.id.last_name })
List<EditText> nameViews;
ButterKnife.apply(nameViews, DISABLE);
ButterKnife.apply(nameViews, ENABLED, false);

Listener监听

通过@OnClick注解绑定监听方法

@OnClick(R.id.submit)
public void submit(View view) {
  // TODO submit data to server...
}

方法的参数是可以改变的 ,如果是特殊的对象,它将会自动转化

@OnClick(R.id.submit)
public void sayHi(Button button) {
  button.setText("Hello!");
}

当然对于同类型控件的通用事件处理,我们也可以把它们写在一起

@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中绑定一个布局的时候,必须在onDestroyView将View设为null,我们可以调用unbinder.unbind()方法来取消绑定

public class FancyFragment extends Fragment {
  @BindView(R.id.button1) Button button1;
  @BindView(R.id.button2) Button button2;
  private Unbinder unbinder;

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

  @Override public void onDestroyView() {
    super.onDestroyView();
    unbinder.unbind();
  }
}

默认情况下,如果找不到资源id,会抛出异常,但是我们可以使用@Nullable和@Optional注解来防止程序崩溃。

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

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

最后的彩蛋~

ButterKnife额外的提供了findById 方法给我们进行绑定操作。。。。。我满怀期待的查看了源码,却发现。。

 /** Simpler version of {@link View#findViewById(int)} which infers the target type. */
  @SuppressWarnings({ "unchecked", "UnusedDeclaration" }) // Checked by runtime cast. Public API.
  @CheckResult
  public static <T extends View> T findById(@NonNull View view, @IdRes int id) {
    return (T) view.findViewById(id);
  }

  /** Simpler version of {@link Activity#findViewById(int)} which infers the target type. */
  @SuppressWarnings({ "unchecked", "UnusedDeclaration" }) // Checked by runtime cast. Public API.
  @CheckResult
  public static <T extends View> T findById(@NonNull Activity activity, @IdRes int id) {
    return (T) activity.findViewById(id);
  }

  /** Simpler version of {@link Dialog#findViewById(int)} which infers the target type. */
  @SuppressWarnings({ "unchecked", "UnusedDeclaration" }) // Checked by runtime cast. Public API.
  @CheckResult
  public static <T extends View> T findById(@NonNull Dialog dialog, @IdRes int id) {
    return (T) dialog.findViewById(id);
  }
}

发现JakeWharton大神仅仅是帮我们用泛型的方法自动转化了类型-.-
真的是意想不到的彩蛋啊,哈哈哈哈~

参考文章
Butterknife使用指南
Android Butterknife 8.4.0 使用方法总结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值