Butter Knife —— 最好用的View注入

转载请标明出处:http://blog.csdn.net/xx326664162/article/details/52082732 文章出自:薛瑄的博客

你也可以查看我的其他同类文章,也会让你有一定的收货!

强烈建议使用DataBinding 来代替Butter Knife

最近在看腾讯Bugly公众号的文章,看到了关于Butter Knife源码的分析,之前在JakeWharton的github上有看到这个项目,没怎么注意,别人都已经开始分析源码了,应该挺火的,赶紧去学习了一下。

看了官网上的文档,挺简单,也很实用,决定以后就用这个库了。
下面是我翻译的官方文档,诸位看官轻喷。官方文档也挺简单,英语好的不好的,都建议去看看原文。

Butter Knife

本文章翻译自:http://jakewharton.github.io/butterknife/
参考:Android Butter Knife 框架——最好用的View注入
http://blog.csdn.net/watermusicyes/article/details/47417257

Butter Knife,专门为Android View设计的绑定注解。

使用@BindView和一个视图ID注释字段 ,Butter Knife自动找到并把相应的视图布局。

class ExampleActivity extends Activity {
  @BindView(R.id.title) TextView title;
  @BindView(R.id.subtitle) TextView subtitle;
  @BindView(R.id.footer) TextView footer;

  @Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.simple_activity);
    ButterKnife.bind(this);
    // TODO Use fields...
  }
}

生成代码来执行查询,而不是缓慢的反射,。调用 bind委托这个生成的代码,你可以看到和调试。

上面的示例生成的代码大致相当于以下:

public void bind(ExampleActivity activity) {
  activity.subtitle = (android.widget.TextView) activity.findViewById(2130968578);
  activity.footer = (android.widget.TextView) activity.findViewById(2130968579);
  activity.title = (android.widget.TextView) activity.findViewById(2130968577);
}

资源绑定

使用@BindBool, @BindColor, @BindDimen, @BindDrawable, @BindInt, @BindString绑定预定义的资源,绑定一个 R.boolID(或指定类型)到其相应的字段。

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

非Activity中使用绑定

您还可以执行绑定在任意对象通过提供自己的视图根。

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

在Adapter中的用法

还有一种比较常见的场景,就是在ListView的Adapter中,我们常常会使用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);
    }
  }
}

你可以看到这个实现的行动在提供的示例中。

你可以在你想的任何地方调用ButterKnife.bind,否则就是调用findViewById

其他提供的绑定api:

  • 绑定任意对象使用一个activity作为根视图。如果你使用像MVC模式,你使用 ButterKnife.bind(this, activity)绑定controller 来使用它的activity,

  • 使用 ButterKnife.bind(this)绑定一个子视图到字段。如果你使用 标签在一个自定义视图布局和inflate 构造函数,可以在后面立即调用这个。另外,自定义视图类型inflate 从XML可以在 onFinishInflate()回调中使用它。

View 列表

你可以一次性将多个views绑定到一个List或数组中:

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

apply()方法允许你对在list中的所有view进行操作.

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

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

Android的Property(配置信息)也可以被用在apply方法中,作为apply方法的参数。

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

监听器绑定

监听器也可以自动配置进方法中:

@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!");
}

同时指定多个id的控件到同一个事件监听上:

@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!
  }
}

绑定重置

Fragment的生命周期与Activity不同。在Fragment中,我们可能会在onCreateView中绑定一个布局,并在onDestroyView中设置所有view为null.

当你调用bind()函数后返回一个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();
  }
}

可选的绑定:

在默认情况下, @bind和监听器的绑定都是需要的,如果目标view没有找到的话,Butter Knife将会抛出一个异常。

为了抑制这种行为和创建一个可选的绑定,在字段上增加一个注解 @Nullable或者在方法上增加一个注解@Optional

注意:任何注释命名 @Nullable可用于字段。这是鼓励使用 @Nullable注释的 Android’s “support-annotations” library.

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

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

对于包含多个方法的监听器

当一个监听器包含多个回调函数时,使用方法注入能够对其中任何一个函数进行绑定。每一个注解都会绑定到一个默认的回调。使用 callback参数指定一个替代。:

@OnItemSelected(R.id.list_view)
void onItemSelected(int position) {
  // TODO ...
}

@OnItemSelected(value = R.id.maybe_missing, callback = NOTHING_SELECTED)
void onNothingSelected() {
  // TODO ...
}

简单的findViewById

Butter Knife提供了一个findViewById的简化代码findById,用这个方法可以在View、Activity和Dialog中找到想要View,而且,该方法使用的泛型来对返回值进行转换,也就是说,你可以省去findViewById前面的强制转换了。

View view = LayoutInflater.from(context).inflate(R.layout.thing, null);
TextView firstName = ButterKnife.findById(view, R.id.first_name);
TextView lastName = ButterKnife.findById(view, R.id.last_name);
ImageView photo = ButterKnife.findById(view, R.id.photo);

如果你只是使用这个方法,可以使用静态引入ButterKnife.findById。

Download

GRADLE

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

License

Copyright 2013 Jake Wharton

Licensed under the Apache License, Version 2.0 (the “License”);
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an “AS IS” BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

关注我的公众号,轻松了解和学习更多技术
这里写图片描述

发布了244 篇原创文章 · 获赞 799 · 访问量 234万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 代码科技 设计师: Amelia_0503

分享到微信朋友圈

×

扫一扫,手机浏览