【开源项目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 ...
随机推荐
- python svn
svn 0.3.36 Downloads ↓ Intuitive Subversion wrapper. Introduction svn is a simple Subversion library ...
- react native listview 一个有用的属性,用作两列布局
contentContainerStyle:设置listview包裹内容的属性 <ListView contentContainerStyle={{flexDirection:'row',fle ...
- iOS的几种定时器
//gcd的定时器timer必须先保存为一个属性或者成员变量 @property (nonatomic , assign) dispatch_source_t timer; //第一种 每一秒执行一次 ...
- SSH下载的方法
----------------------------------下作下载方法一----------------------------------------------------------- ...
- PHP函数前面的@。
@是可以屏蔽函数执行过程中遇到问题而产生的一些错误.警告信息,这样用户就看不到程序的出错信息.这样除了用户界面会友好一些外,更重要的是安全性,因为屏蔽了出错文件的路径等信息. 比如说这个: for($ ...
- NoSQL 数据建模技术(转)
本文转载自:http://coolshell.cn/articles/7270.html ================================================ 全文译自墙外 ...
- C# 绘制统计图(柱状图, 折线图, 扇形图)
统计图形种类繁多, 有柱状图, 折线图, 扇形图等等, 而统计图形的绘制方法也有很多, 有Flash制作的统计图形, 有水晶报表生成统计图形, 有专门制图软件制作, 也有编程语言自己制作的:这里我们用 ...
- js查看浏览器类型和版本
var Sys = {}; var ua = navigator.userAgent.toLowerCase(); var s; var scan; (s = ua.match(/msie ([\d. ...
- 新建VM_Script
在Hyper-V群集中,不需要设置VM的自启动,当宿主机意外关机重新启动后,上面的VM会自动转移到另一台主机:如果另一台主机处于关机状态,则宿主机重新启动后,其VM也会自启动(如果其VM在宿主机关机前 ...
- 05_android入门_GET方式实现登陆(在控件上显示服务端返回的内容)
当点击登陆之后,怎么把server端返回的数据,写到指定的控件上尼?,在android怎么实现尼?以下我们通过详细的代码进行分析和实现,希望能对你,在学习android知识上有所帮助. 以下通过代码说 ...