Android Butter Knife 框架——最好用的View注入
2016-03-18 23:54
399 查看
最近在看GitHub上的一些代码时,发现很多工程都用到了Butter Knife这个框架,能节省很多代码量。像
抱着学习的心态看了官网上的文档,挺简单,也很实用,决定以后就用这个库了。
下面是我翻译的官方文档,诸位看官轻喷。官方文档也挺简单,英语好的不好的,都建议去看看原文。
image.png
Butter Knife,专门为Android View设计的绑定注解。
请注意,相比与缓慢的反射机制,Butter Knife的代码是生成的,因此不必担心注解的性能问题。调用
例如上面的例子,生成的代码大致如下所示:
例如在Fragment中:
还有一种比较常见的场景,就是在ListView的Adapter中,我们常常会使用ViewHolder:
你能在提供给的例子中找到上述代码。
提供的其他绑定API:
使用Ac
4000
tivity在任意对象中进行绑定。如果你使用了类似MVC的编程模式,你可以使用
使用
使用这种绑定时,你可以使用
而
Android的
监听器所有的参数都是可选的:
定义一个其他的类型,Butter Knife也能识别:
同时指定多个id的控件到同一个事件监听上:
自定义View绑定事件监听时无需ID:
如果你并不想接收到这样的信息,那么就在你的方法或变量上使用
这个注解来自于Android的"support-annotations"库,使用这些注解对你的代码有好处,关于该库的详情,可以点击此处:Android Tools Project
使用该注解后的代码如下:
简单的
Butter Knife提供了一个
如果你只是使用这个方法,可以使用静态引入
查看Butter Knife的API文档现在也可以查看:Butter Knife Javadoc
注意在
你也有可能需要如下配置:
findViewById这种代码就不用再出现了,而且这个框架也提供了很多其他有用的注解。
抱着学习的心态看了官网上的文档,挺简单,也很实用,决定以后就用这个库了。
下面是我翻译的官方文档,诸位看官轻喷。官方文档也挺简单,英语好的不好的,都建议去看看原文。
image.png
Butter Knife
本文章翻译自:http://jakewharton.github.io/butterknife/Butter Knife,专门为Android View设计的绑定注解。
简介
使用@Bind注解并传入一个View ID,Butter Knife 就可以找到并且自动地对你的布局中的View进行转换并绑定到类成员上。
class ExampleActivity extends Activity { @Bind(R.id.title) TextView title; @Bind(R.id.subtitle) TextView subtitle; @Bind(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... } }
请注意,相比与缓慢的反射机制,Butter Knife的代码是生成的,因此不必担心注解的性能问题。调用
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。使用时对应的注解需要传入对应的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 // ... }
在非Activity中使用绑定
Butter Knife提供了bind的几个重载,只要传入跟布局,便可以在任何对象中使用注解绑定。例如在Fragment中:
public class FancyFragment extends Fragment { @Bind(R.id.button1) Button button1; @Bind(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; } }
还有一种比较常见的场景,就是在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 { @Bind(R.id.title) TextView name; @Bind(R.id.job_title) TextView jobTitle; public ViewHolder(View view) { ButterKnife.bind(this, view); } } }
你能在提供给的例子中找到上述代码。
ButterKnife.bind函数可以被放在任何你想使用
findViewById的地方。
提供的其他绑定API:
使用Ac
4000
tivity在任意对象中进行绑定。如果你使用了类似MVC的编程模式,你可以使用
ButterKnife.bind(this, activity)在Controller中进行绑定
使用
ButterKnife.bind(this)绑定一个布局的子布局到变量上。如果你在布局中使用了
<merge>标签并且在自定义的控件构造时inflate这个布局,你可以在inflate之后立即调用它。或者,你可以在
onFinishInflate()回调中使用它。
View 列表
你可以一次性将多个views绑定到一个List或数组中:
@Bind({ R.id.first_name, R.id.middle_name, R.id.last_name }) List<EditText> nameViews;
使用这种绑定时,你可以使用
apple函数。该函数相当于将在这个列表中每一个元素上进行调用:
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也可以使用到
apple方法中:
ButterKnife.apply(nameViews, View.ALPHA, 0.0f);
监听器绑定
在Butter Knife中,监听器也自动地配置到方法上:@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... }
定义一个其他的类型,Butter Knife也能识别:
@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绑定注意:
Fragment的生命周期与Activity不同。在Fragment中,我们可能会在onCreateView中绑定一个布局,并在
onDestroyView中设置所有view为
null.此时,你就需要Butter Knife提供的
undind函数来做此事。
public class FancyFragment extends Fragment { @Bind(R.id.button1) Button button1; @Bind(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; } @Override public void onDestroyView() { super.onDestroyView(); ButterKnife.unbind(this); } }
可选的绑定:
在默认情况下,@bind和监听器的绑定都是需要的,如果目标view没有找到的话,Butter Knife将会抛出一个异常。
如果你并不想接收到这样的信息,那么就在你的方法或变量上使用
@Nullable吧。
这个注解来自于Android的"support-annotations"库,使用这些注解对你的代码有好处,关于该库的详情,可以点击此处:Android Tools Project
使用该注解后的代码如下:
@Nullable @Bind(R.id.might_not_be_there) TextView mightNotBeThere; @Nullable @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。
使用
Butter Knife的代码和例子都可以在GitHub上找到:Butter Knife GitHub查看Butter Knife的API文档现在也可以查看:Butter Knife Javadoc
MAVEN
声明以下依赖库:<dependency> <groupId>com.jakewharton</groupId> <artifactId>butterknife</artifactId> <version>(insert latest version)</version> </dependency>
GRADLE
compile 'com.jakewharton:butterknife:(insert latest version)'
注意在
build.gradle中取消
lint的如下警告:
lintOptions { disable 'InvalidPackage' }
你也有可能需要如下配置:
packagingOptions { exclude 'META-INF/services/javax.annotation.processing.Processor' }
ProGuard
Butter Knife使用动态生成的代码,这可能使ProGuard认为这些代码是无用的。为了避免这些代码被混淆,你可以添加如下代码到你的ProGuard中:-keep class butterknife.** { *; } -dontwarn butterknife.internal.** -keep class **$$ViewBinder { *; } -keepclasseswithmembernames class * { @butterknife.* <fields>; } -keepclasseswithmembernames class * { @butterknife.* <methods>; }
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.
相关文章推荐
- andorid studio 启动 fetching android sdk..问题解决办法
- Android+PHP+MYSQL开发简单实例
- 如何获取 Android 设备的CPU核数、时钟频率以及内存大小
- Android常用权限permission列表摘录
- Error inflating class android.widget.CheckBox
- Android为CustomView在xml中设置属性
- Android 全屏显示
- Android全屏启动页进入非全屏activity界面部分内容被状态栏遮住
- MVP模式在Android中的使用
- android学习笔记——ListView的使用
- Android四大组件之Service复习笔记
- Android——Activity生命周期(转)
- Android 获得手机电池的情况
- Android-在动作栏中添加和删除选项卡
- Android中四大组件总结
- Android——Activity和Intent及Activity的生命周期
- 下载APK,检测APK是否安装,检测程序是否运行
- android中的Binder(android内核学习记录)
- 状态模式与android状态机
- AlarmManager系统闹钟