【ButterKnife】 安卓程序猿的一大利器
注:近期才看到的这个类库,来自于jakewharton大神的力作,安卓里面的视图注入库
另小弟水平有限,翻译的不好,还请多多指正
首先是地址(托管在github上):http://jakewharton.github.io/butterknife/
进去后首先看到的是关于使用方法的解说,翻译部分正式開始(通俗且精简化,建议对比着看)!
简单介绍:
程序猿都是懒惰的,不想写一大堆像以下这种代码
class ExampleActivity extends Activity {
TextView title;
TextView subtitle;
TextView footer; @Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_activity);
title = (TextView) findViewById(R.id.title);
subtitle = (TextView) findViewById(R.id.subtitle);
footer = (TextView) findViewById(R.id.footer); // TODO Use views...
}
}
这样非常不好,因此我们就找到了一个方法,使用魔法一般的注解,来浓缩代码,就像以下这样
class ExampleActivity extends Activity {
@Magic(R.id.title) TextView title;
@Magic(R.id.subtitle) TextView subtitle;
@Magic(R.id.footer) TextView footer; @Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_activity);
// TODO Use "injected" views...
}
}
然而,这样尽管看起来非常酷,非常Magic,只是还是会带来严重的执行时的问题
于是,我们就利用javac 编译器中一大利器来生成前面样例中的findViewById
的引用,
而且继续保持代码的精简
,继续看以下的代码
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...
}
}
在原本Magic的地方使用inject
方法来替代,以下是该方法的一段代表(This
method delegates to generated code 不明),能够看并debug
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);
}
(这段能够忽略吗?貌似翻译不正确,看不太懂)有些人称这个为视图注入,并加到了传统的依赖注入框架中,也许在术语上有错误,只是也许有一点作用.......
NON-ACTIVITY INJECTION
我们能够对随意的View对象使用注入,当然了,须要提供view root的对象
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;
}
}
另外一个用处是简化list adapter中的View Holder模式,这个样例能够在提供的sample中看到
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 convertView;
} static class ViewHolder {
@InjectView(R.id.title) TextView name;
@InjectView(R.id.job_title) TextView jobTitle; public ViewHolder(View view) {
ButterKnife.inject(this, view);
}
}
}
其它的API(这段真心建议看一下原版)
ButterKnife.inject(this,
activity)
方法
ButterKnife.inject(this)(在前面样例的
onCreate方法中就是,不懂的能够參考这个),假设你在一个layout
CLICK LISTENER INJECTION
Click listener 也能够被注入
@OnClick(R.id.submit)
public void submit() {
// TODO submit data to server...
}
也能够加一个view对象,特定的类型会被自己主动转换
@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();
}
}
INJECTION RESET
Fragments 有比Avtivity很多其它的生命周期 ,假设须要在onCreateView中注入一个fragment,在onDestroyView中销毁它
Butter Knife 有一个reset
方法自己主动实现它
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(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);
}
}
OPTIONAL INJECTIONS
默认情况下
@InjectView
和@OnClick
都是必须加上的,假设当前对象不存在,就会抛出一个异常
@InjectView
为了压制这个异常,能够在变量或者方法上增加一下注解
@Optional @InjectView(R.id.might_not_be_there) TextView mightNotBeThere; @Optional @OnClick(R.id.maybe_missing) void onMaybeMissingClicked() {
// TODO ...
}
BONUS
这段看不太懂,大意预计是除了以上注入方法之外另一种,类型会自己主动转换,须要静态导入ButterKnife.findById
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);
Download:当前版本号 4.0.1
详细:http://github.com/JakeWharton/butterknife
jar包:http://repo1.maven.org/maven2/com/jakewharton/butterknife/4.0.1/butterknife-4.0.1.jar
Maven配置:假设你是用maven开发的童鞋,请自觉加上例如以下依赖
<dependency>
<groupId>com.jakewharton</groupId>
<artifactId>butterknife</artifactId>
<version>4.0.1</version>
</dependency>
IDE的配置
- IntelliJ IDEA — 假设你是用外部工具管理project (如 Maven pom.xml)
应该能正常工作, 不然就看看这个 http://jakewharton.github.io/butterknife/ide-idea.html
- Eclipse — http://jakewharton.github.io/butterknife/ide-eclipse.html
PROGUARD
使用注入会导致ProGuard 觉得变量未被使用,因此,须要在ProGuard 中增加例如以下字段
-dontwarn butterknife.internal.**
-keep class **$$ViewInjector { *; }
-keepnames class * { @butterknife.InjectView *;}
Having Happy Coding!
应该能正常工作, 不然就看看这个 http://jakewharton.github.io/butterknife/ide-idea.html
PROGUARD
使用注入会导致ProGuard 觉得变量未被使用,因此,须要在ProGuard 中增加例如以下字段
-dontwarn butterknife.internal.**
-keep class **$$ViewInjector { *; }
-keepnames class * { @butterknife.InjectView *;}
Having Happy Coding!
【ButterKnife】 安卓程序猿的一大利器的更多相关文章
- 漫谈程序员(十二)IT程序猿之猿体是革命的本钱
IT程序猿之猿体是革命的本钱 前言 程序猿的一大特点就是加班.加班.不停地加班.... 为了美好的生活,为了生活的更加美好.我们选择勤勤恳恳,踏踏实实. 但是,工作只是生活的一部分.生命中最重要的莫过 ...
- 辛星跟您玩转vim第三节之程序猿特须要的移动方式
前面第二节我首先值得一提的是,我的vim教程pdf版本号已经写完了.大家能够去下载,这里是csdn的下载地址:csdn下载.假设左边的下载地址挂掉了.也能够自行在浏览器以下输入例如以下地址进行下载:h ...
- 站在风口,你或许就是那年薪20w+的程序猿
最近面试了一些人,也在群上跟一些群友聊起,发现现在的互联网真是热,一些工作才两三年的期望的薪资都是十几K的起,这真是让我们这些早几年就成为程序猿的情何以堪!正所谓是站在风口上,猪也能飞起来!我在这里就 ...
- 关于App程序猿泡沫
前言 做开发快七年了,对于程序猿,外行人总有着数不完的讽刺和误解,可是我都懒得去解释.代码搬运工人也好,民工也罢,随他们去说吧.可是网上近期流传的程序猿泡沫,尤其是APP程序猿泡沫的文章导致非常多我们 ...
- 程序猿的编程神器 - vim
一.官方文档: 当你首次安装好 Vim 之后.能够用 :help tutor 或者 :help tutor@cn 命令.进入一个30分钟的 Vim 新手教程.你也能够下载一个 Vim Document ...
- 程序猿进化 - 在拉钩子1024对APE节讲座计划
注意:下面这篇文章来自于我在网上拉勾1024对APE节现场演示程序. 我是蒋宇捷,信天创投的合伙人.之前是百度魔图的联合创始人. 我先做个自我介绍,事实上每次介绍自己事实上是非常痛苦的事情,由于我前不 ...
- 七个 Android 程序猿提高效率必备工具
Android 程序猿提高效率必备工具 0x00 Code tree for GitHub 这个 Chrome 浏览器插件.Github 作为最大同性交友网站,每天的工作几乎是从打开这个网站开始的.当 ...
- 聊聊我面试过的一个最奇葩的 Java 程序猿!
上周我聊了聊最让我反感的 10 种程序猿,无奈一个小时就进行了删除,详细原因就不说了,容易招黑. 今天聊的我面试过的最奇葩的一个程序猿,绝对是奇葩中的奇葩,简直是程序猿中的另类,最让我反感的程序猿又添 ...
- 996ICU与程序猿的个人成长
目录 规划 学习 专业领域知识 知识广度 第二职业 理财 借势 添砖加瓦 最近一段时间,996ICU在互联网界引发"大地震",从普通员工.行业大佬甚至官媒都进行了发声,大家对这个问 ...
随机推荐
- ASP.NET Web Api OwinSelfHost Restful 使用
一.前言 总结一下什么是RESTful架构: (1)每一个URI代表一种资源: (2)客户端和服务器之间,传递这种资源的某种表现层: (3)客户端通过四个HTTP动词,对服务器端资源进行操作,实现&q ...
- Extjs 基础篇—— Function基础
这里主要是JS的基础知识,也是深入理解Ext的基础.1.参数可变长,注意跟Java还是有一点区别的.例: 1.function getUser(name,age){ 2.alert("nam ...
- Github中展示demo
原文链接http://www.jianshu.com/p/75e30889e70a 第一步:找到Settings,点击 第二步:找到githubPages点击none,切换到master branch ...
- CF1030A 【In Search of an Easy Problem】
题目巨简单,主要是给大家翻译一下 给n个数,其中存在1就输出HARD,否则输出EASY,不区分大小写 #include<iostream> #include<cstdio> u ...
- 使用SQL语句查询某表中所有的主键、唯一索引以及这些主键、索引所包含的字段(转)
SELECT 索引名称 = a.name , 表名 = c.name , 索引字段名 = d.name , 索引字段位置 = d.colid FROM sysindexes a JOIN sysind ...
- linux添加桌面快捷方式
linux通过软件中心安装的程序快捷图标都放在/usr/share/applications/目录下.点选一个图标右键,选择复制到,目录选择桌面即可. 但是有一些软件自行安装后,在那个目录里没有 ...
- Python并发编程-协程实现socketserver
#server.py from gevent import monkey;monkey.patch_all() import socket import gevent sk = socket.sock ...
- 【面试总结】网易2019秋招一站式面试总结(等offer中……)
岗位:运维工程师(网易杭州) 面试时间:一天 上午十一点二十,准时开启面试,初面面试官是个看起来就像是主管的人,厚实的身体,中气浑厚的声音,整齐朴素的衬衫. 简要问题摘录如下:(后续补充答案内容) 1 ...
- 一、redis系列之基础知识与centos下环境搭建
1. Redis 与其他 key - value 缓存产品有以下三个特点: Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用. Redis不仅仅支持简单的ke ...
- 文件哈希审计工具md5deep/hashdeep
文件哈希审计工具md5deep/hashdeep 在数据取证中,通常需要验证文件的哈希值,以判断文件是否已知好文件,或者文件是否被修改过.Kali Linux提供专用工具hashdeep.该工具的 ...