【开源项目7】Android视图注入库:butterknife
介绍
ButterKnife通过@InjectView和视图的ID注解的变量去找到并自动转换为你布局上相应的布局视图。
class ExampleActivity extends Activity {
@InjectView(R.id.title) TextView title;
@InjectView(R.id.subtitle) TextView subtitle;
@InjectView(R.id.footer) TextView footer;
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_activity);
ButterKnife.inject(this);
// TODO Use "injected" views...
}
}
与缓慢的反射机制不同的是,产生的代码是用来执行视图的查表(查找视图)操作。调用Inject方法生成的代码可以查看且调试。上面例子中的代码可以粗略等同于下面:
public void inject(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);
}
非activity注入
你也可以提供自己的根视图对任意对象执行注入:
public class FancyFragment extends Fragment {
@InjectView(R.id.button1) Button button1;
@InjectView(R.id.button2) Button button2;
@Override View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fancy_fragment, container, false);
ButterKnife.inject(this, view);
// TODO Use "injected" views...
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 {
@InjectView(R.id.title) TextView name;
@InjectView(R.id.job_title) TextView jobTitle;
public ViewHolder(View view) {
ButterKnife.inject(this, view);
}
}
}
你可以在上面例子中查看其行为的实现。你可以在任意可以使用findViewById的地方使用ButterKnife.inject。
其他提供的注入API:
可以使用activity作为根视图对任意对象进行注入。如果你使用了类似MVC的架构,你可以通过在控制器(C)的activity使用ButterKnife.inject(this, activity)对其进行注入。
可以使用ButterKnife.inject(this)对子视图进行注入。如果你在布局中使用<merge>标签而且载入了自定义控件,可以在后面立即调用它。或者通过xml载入的自定义视图,可以在onFinishInflate()回调中使用它。
视图列
你可以把多个视图集中到列表或者数组中。
@InjectViews({ R.id.first_name, R.id.middle_name, R.id.last_name })
List<EditText> nameViews;
apply方法可以一次性执行列表中所有视图的行为:
ButterKnife.apply(nameViews, DISABLE);
ButterKnife.apply(nameViews, ENABLED, false);
Action和Setter接口允许定义简单的行为:
static final Action<View> DISABLE = new Action<>() {
@Override public void apply(View view, int index) {
view.setEnabled(false);
}
}
static final Setter<View, Boolean> ENABLED = new Setter<>() {
@Override public void set(View view, Boolean value, int index) {
view.setEnabled(value);
}
}
Android的自带属性也可以用apply方法。
ButterKnife.apply(nameViews, View.ALPHA, 0);
点击监听注入
点击监听也可以自动设置到方法。
@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();
}
}
注入重置
fragment比起activity有更加不同的声明周期,当在fragment的onCreateView里注入时,应该在onDestroyView里设置视图为空。ButterKnife有一个重置方法可以自动做这个操作。
public class FancyFragment extends Fragment {
@InjectView(R.id.button1) Button button1;
@InjectView(R.id.button2) Button button2;
@Override View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fancy_fragment, container, false);
ButterKnife.inject(this, view);
// TODO Use "injected" views...
return view;
}
@Override void onDestroyView() {
super.onDestroyView();
ButterKnife.reset(this);
}
}
可选注入
默认情况下,@InjectView和@OnClick是必须的(此处的必须应该是对应后面一句话而言的)。如果目标视图未找到会抛异常。为了禁止这种行为的出现并创建一个可选的注入,添加@Optional注解到值或方法上。
@Optional @InjectView(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 ...
}
额外奖励
包含的两个简化代码的findById方法仍需要在view或activity查找视图。它使用generics推断返回类型并自动执行转换。
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添加静态引入会更加有趣。介绍
ButterKnife通过@InjectView和视图的ID注解的变量去找到并自动转换为你布局上相应的布局视图。
class ExampleActivity extends Activity {
@InjectView(R.id.title) TextView title;
@InjectView(R.id.subtitle) TextView subtitle;
@InjectView(R.id.footer) TextView footer;
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_activity);
ButterKnife.inject(this);
// TODO Use "injected" views...
}
}
与缓慢的反射机制不同的是,产生的代码是用来执行视图的查表(查找视图)操作。调用Inject方法生成的代码可以查看且调试。上面例子中的代码可以粗略等同于下面:
public void inject(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);
}
非activity注入
你也可以提供自己的根视图对任意对象执行注入:
public class FancyFragment extends Fragment {
@InjectView(R.id.button1) Button button1;
@InjectView(R.id.button2) Button button2;
@Override View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fancy_fragment, container, false);
ButterKnife.inject(this, view);
// TODO Use "injected" views...
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 {
@InjectView(R.id.title) TextView name;
@InjectView(R.id.job_title) TextView jobTitle;
public ViewHolder(View view) {
ButterKnife.inject(this, view);
}
}
}
你可以在上面例子中查看其行为的实现。你可以在任意可以使用findViewById的地方使用ButterKnife.inject。
其他提供的注入API:
可以使用activity作为根视图对任意对象进行注入。如果你使用了类似MVC的架构,你可以通过在控制器(C)的activity使用ButterKnife.inject(this, activity)对其进行注入。
可以使用ButterKnife.inject(this)对子视图进行注入。如果你在布局中使用<merge>标签而且载入了自定义控件,可以在后面立即调用它。或者通过xml载入的自定义视图,可以在onFinishInflate()回调中使用它。
视图列
你可以把多个视图集中到列表或者数组中。
@InjectViews({ R.id.first_name, R.id.middle_name, R.id.last_name })
List<EditText> nameViews;
apply方法可以一次性执行列表中所有视图的行为:
ButterKnife.apply(nameViews, DISABLE);
ButterKnife.apply(nameViews, ENABLED, false);
Action和Setter接口允许定义简单的行为:
static final Action<View> DISABLE = new Action<>() {
@Override public void apply(View view, int index) {
view.setEnabled(false);
}
}
static final Setter<View, Boolean> ENABLED = new Setter<>() {
@Override public void set(View view, Boolean value, int index) {
view.setEnabled(value);
}
}
Android的自带属性也可以用apply方法。
ButterKnife.apply(nameViews, View.ALPHA, 0);
点击监听注入
点击监听也可以自动设置到方法。
@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();
}
}
注入重置
fragment比起activity有更加不同的声明周期,当在fragment的onCreateView里注入时,应该在onDestroyView里设置视图为空。ButterKnife有一个重置方法可以自动做这个操作。
public class FancyFragment extends Fragment {
@InjectView(R.id.button1) Button button1;
@InjectView(R.id.button2) Button button2;
@Override View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fancy_fragment, container, false);
ButterKnife.inject(this, view);
// TODO Use "injected" views...
return view;
}
@Override void onDestroyView() {
super.onDestroyView();
ButterKnife.reset(this);
}
}
可选注入
默认情况下,@InjectView和@OnClick是必须的(此处的必须应该是对应后面一句话而言的)。如果目标视图未找到会抛异常。为了禁止这种行为的出现并创建一个可选的注入,添加@Optional注解到值或方法上。
@Optional @InjectView(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 ...
}
额外奖励
包含的两个简化代码的findById方法仍需要在view或activity查找视图。它使用generics推断返回类型并自动执行转换。
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添加静态引入会更加有趣。
【开源项目7】Android视图注入库:butterknife的更多相关文章
- 开源项目之Android 结束篇
随着公司新的需求以及Android嵌入式的深入,我已经没有多余的时间去扩展学习与Sip或UI不相关的Android开源项目,至此结束! 感想:研究Android已经一年半载了,白天忙公司项目,晚上扩展 ...
- [Android 开源项目学习]Android的UITableView(1)
最近由于项目加急,手里有好多看了差不多的开源项目,其中好多是大家经常用到的.图片的缓存BitmapFun(Android的文档中),AfinalMap,下拉刷新PullToRefresh等等 ...
- 开源项目之Android Afinal框架
项目如图: 本文参考网络! Afinal是一个开源的android的orm和ioc应用开发框架,其特点是小巧灵活,代码入侵量少.在android应用开发中,通过Afinal的ioc框架,诸如ui绑定, ...
- 【开源项目】Android 手写记事 App(半成品)
该项目已上传到 CSDN 的 Git 平台中 项目地址:https://code.csdn.net/gd920129/whiteboard GIT SSH:git@code.csdn.net:gd92 ...
- Android 开源项目及其学习
Android 系统研究:http://blog.csdn.net/luoshengyang/article/details/8923485 Android 腾讯技术人员博客 http://hukai ...
- Android 开源项目维护者宣布退出
Android开源项目(Android Open Source Project,AOSP)的长期维护者Jean-Baptiste Quéru在Google+上宣布退出,他退出AOSP项目的原因被认为与 ...
- Android开源项目分包方式学习(eoe、oschina、github)
总感觉Android中关于分包的文章很少,或者几乎可以说没有.但是合理地分包,又可以使整个项目模块化,减少包与包之间的依赖,让整个项目的框架更加清晰,更利于后续功能的拓展. 因为没有相关的文章,所以这 ...
- Android github上开源项目、酷炫的交互动画和视觉效果地址集合
Android上开源的酷炫的交互动画和视觉效果:http://blog.csdn.net/u013278099/article/details/50323689 Awesome-android-ui: ...
- [Android开源项目] GitHub开源项目总结 (转)
[Android开源项目] GitHub开源项目总结 GitHub开源项目android-styled-dialogs http://neast.cn/forum.php?mod=viewthread ...
随机推荐
- 自定义滚动控件(Pagecontrol)
// // MyPageCorol.h // lejiahui // // Created by iOS开发 on 16/4/10. // Copyright © 2016年 zhongmingwuy ...
- mysql中key 、primary key 、unique key 与index区别
一.key与primary key区别 CREATE TABLE wh_logrecord ( logrecord_id ) NOT NULL auto_increment, ) default NU ...
- flash 定义主舞台窗口大小
1:[SWF(width=100 height=100)] 写在主类上面2:设置stageScaleMode属性为false;
- 8.实现(Realization)
实现关系是用来描述接口和实现接口的类或者构建结构之间的关系,接口是操作的集合,而这些操作就用于规定类或者构建结构的一种服务. 在接口和类之间的实现关系中,类实现了接口,类中的操作实现了接口中所声明的操 ...
- Form时间交叉验证唯一性
*================================================== ** PROCEDURE: check_effcitive_utl Descr ...
- 习总强调网络安全 ,咱们国产SSL证书必须加快普及速度
上海(2014 年 2 月 27 日)—— 央视新闻联播 27 日报道中央网络安全和信息化领导小组于当日成立的消息及习总在该小组首次会议上的重要讲话.据悉,该小组由习总任小组长,李克强.刘云山任副组长 ...
- Nutch 2.2+MySQL+Solr4.2实现网站内容的抓取和索引
原文地址: http://blog.sina.com.cn/s/blog_3c9872d00101p4f0.html Nutch 2.2.1发布快两月了,该版本与Nutch之前版本相比,有较大变化,特 ...
- ISO13485给企业带来的益处
1.ISO13485变强制性认证,日益受到欧美和中国政府机构的重视,有利于消除国际贸易中的技术壁垒,是进入国际市场的通行证: 2.提高和改善企业的管理水平,增加企业的知名度: 3.提高和保证产品的质量 ...
- C++学习笔记之继承
一.基类和派生类 很多时候,一个类的对象也“是”另一个类的对象,如矩形是四边形,在C++中,矩形类Rectangle可以由四边形类Quad继承而来,于是,四边形类Quad是基类,矩形类Rectangl ...
- android用NDK编译出so最简单的方法
其实只要是有个jni的文件夹,再放个Android.mk LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hell ...