最近在研究这个玩意儿AndroidAnnotation。在github上使用频率还是挺高的。说是这个框架只有50来kb,当时是抱着试试的态度耍耍来着,感觉挺有意思。不过一开始使用的时候比较操蛋,总是报错,还发现不了错误在什么地方。汗,没法找啊!还以为1小时就能搞定的东西,非得耗费我远超一小时的时间才搞出来。
开源的玩意儿,莫名的好感有木有。
以前也发现不少注解类的代码。类似这样:
步骤一:先搞一个注解
<span style="font-size:18px;">@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectView {
/**
* The resource id of the View to find and inject.
*/
public int value();
}</span>
步骤二:再来一个工具类
<span style="font-size:18px;">package com.lashou.androidtest.injector;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import android.app.Activity;
/**
* Very lightweight form of injection, inspired by RoboGuice, for injecting common ui elements.
* <p>
* Usage is very simple. In your Activity, define some fields as follows:
*
* <pre class="code">
* @InjectView(R.id.fetch_button)
* private Button mFetchButton;
* @InjectView(R.id.submit_button)
* private Button mSubmitButton;
* @InjectView(R.id.main_view)
* private TextView mTextView;
* </pre>
* <p>
* Then, inside your Activity's onCreate() method, perform the injection like this:
*
* <pre class="code">
* setContentView(R.layout.main_layout);
* Injector.get(this).inject();
* </pre>
* <p>
* See the {@link #inject()} method for full details of how it works. Note that the fields are
* fetched and assigned at the time you call {@link #inject()}, consequently you should not do this
* until after you've called the setContentView() method.
*/
public final class Injector {
private final Activity mActivity;
private Injector(Activity activity) {
mActivity = activity;
}
/**
* Gets an {@link Injector} capable of injecting fields for the given Activity.
*/
public static Injector get(Activity activity) {
return new Injector(activity);
}
/**
* Injects all fields that are marked with the {@link InjectView} annotation.
* <p>
* For each field marked with the InjectView annotation, a call to
* {@link Activity#findViewById(int)} will be made, passing in the resource id stored in the
* value() method of the InjectView annotation as the int parameter, and the result of this call
* will be assigned to the field.
*
* @throws IllegalStateException if injection fails, common causes being that you have used an
* invalid id value, or you haven't called setContentView() on your Activity.
*/
public void inject() {
for (Field field : mActivity.getClass().getDeclaredFields()) {
for (Annotation annotation : field.getAnnotations()) {
if (annotation.annotationType().equals(InjectView.class)) {
try {
Class<?> fieldType = field.getType();
int idValue = InjectView.class.cast(annotation).value();
field.setAccessible(true);
Object injectedValue = fieldType.cast(mActivity.findViewById(idValue));
if (injectedValue == null) {
throw new IllegalStateException("findViewById(" + idValue
+ ") gave null for " +
field + ", can't inject");
}
field.set(mActivity, injectedValue);
field.setAccessible(false);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
}
}
}
} </span>
完事儿之后就可以直接使用了
public class InjectorActivity extends ActionBarActivity {
@InjectView(R.id.contentTV)
private TextView contentTV;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Injector.get(this).inject();
contentTV.setText("修改后的文字");
}
}
好像也像是那么回事儿。看着不用写findViewById了。但是真的减少工作量吗?对于快捷键用的比较少的少年,这种方式人家压根儿就不稀罕。我已经习惯findViewById了,干嘛还用你这玩意儿。不是找罪受吗,也不见得你的代码就减少多少,顶多就是变短了,而且执行速度还变慢不少。所以问题来了,运用反射哪家强?
比较靠谱的还是这个传说中的spring出版的玩意儿。AndroidAnnotation。
现在把配置步骤走一遍:
官网下载地址:
https://github.com/excilys/androidannotations
接着往下走,打开Eclipse能打开的工程:
导进去。想立刻跑起来?没戏!
还得配置东西:
选中工程,右键---properties---java compiler---
接着往下走:
没有√号的请勾上,点击Factory path
搞定,现在可以跑起来了。
混淆的时候,要-dontwarn org.springframework.**,不然会报错。
一定要强调一下:
这个开源项目是在编译阶段就已经操作好了,比运行阶段findViewById要快。
如果想要查看源码,直接打开bundle。
将api-source.jar放在libs目录下面,进入Java bulid path
搞定,源码也是可以看的