在Afinal的FinalActivity中可以用注解开给控件对象赋值和设置监听事件,下面是我的一些学习笔记。
下面是应用的实例:
public class MainActivity extends InjectActivity { @ViewInject(id = R.id.editText1)EditText et;//应用注解 @ViewInject(id = R.id.button1, click = "onClick")Button btn;//应用注解</span> @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // et = (EditText) findViewById(R.id.editText1);可以省略 } public void onClick(View v) { et.setText("ok"); } }下面是自定义的注解:
package com.iotek.webservicedemo; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 自定义的注解 * * * Java中提供了四种元注解,专门负责注解其他的注解,分别如下 * * @Retention元注解,表示需要在什么级别保存该注释信息(生命周期)。 * 可选的RetentionPoicy参数包括: * RetentionPolicy.SOURCE: 停留在java源文件, 编译器被丢掉 * RetentionPolicy.CLASS:停留在class文件中,但会被VM丢弃(默认) * RetentionPolicy.RUNTIME:内存中的字节码,VM将在运行时也保留注解, * 因此可以通过反射机制读取注解的信息 * @Target元注解,默认值为任何元素,表示该注解用于什么地方。 * 可用的ElementType参数包括: * ElementType.CONSTRUCTOR:构造器声明 * ElementType.FIELD:成员变量、对象、属性(包括enum实例) * ElementType.LOCAL_VARIABLE: 局部变量声明 * ElementType.METHOD: 方法声明 * ElementType.PACKAGE: 包声明 * ElementType.PARAMETER:参数声明 * ElementType.TYPE:类、接口或enum声明 * ElementType.ANNOTATION_TYPE,注解类型 * @Documented 将注解包含在JavaDoc中 * @Inheried 允许子类继承父类中的注解 * @author yang * */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface ViewInject { public int id(); public String click() default ""; }下面是仿照FinalActivity写的一个实例
package com.iotek.webservicedemo; import java.lang.reflect.Field; import android.app.Activity; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.view.ViewGroup.LayoutParams; /** * 自定义的一个activity 可以用注解来给控件对象赋值和设置监听 * @author yang * */ public class InjectActivity extends Activity { private static final String TAG = "InjectActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public void setContentView(int layoutResID) { super.setContentView(layoutResID); InjectActivity.initInjectView(this); } @Override public void setContentView(View view) { super.setContentView(view); InjectActivity.initInjectView(this); } @Override public void setContentView(View view, LayoutParams params) { super.setContentView(view, params); InjectActivity.initInjectView(this); } /** * 该方法一定要放到setContentView之后执行 * @param activity */ public static void initInjectView(Activity activity) { // decorView是window中的最顶层view,可以从window中获取到decorView, // 然后decorView有个getWindowVisibleDisplayFrame方法可以获取到程序显示的区域, // 包括标题栏,但不包括状态栏。 InjectActivity.initInjectView(activity, activity.getWindow() .getDecorView()); } /** * 通过反射来给对象赋值和设置监听事件 * @param object activity对象 * @param view 用来通过id获取xml文件当中的view对象(view.findViewById(id)) */ public static void initInjectView(Object object, View view) { //要用getDeclaredFields()方法获取所有属性字段 Field[] fields = object.getClass().getDeclaredFields(); Log.i(TAG, object.getClass().getName()); if (fields != null && fields.length > 0) { for (Field field : fields) { //获取属性的注解 ViewInject inject = field.getAnnotation(ViewInject.class); if (inject != null) { //获取注解的id值 int id = inject.id(); Log.i(TAG, field.getName() + "===" + id); try { //允许对私有属性更改 field.setAccessible(true); // 给field赋值 field.set(object, view.findViewById(id)); } catch (Exception e) { e.printStackTrace(); } //获取注解的click值就是自己定义的点击方法 String nameString = inject.click(); if (!TextUtils.isEmpty(nameString)) { try { //获取field的值(变量的值) Object obj = field.get(object); if (obj instanceof View) { ((View) obj) .setOnClickListener(new EventListener( object).click(nameString)); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } } }下面是 EventListener这个类
package com.iotek.webservicedemo; import java.lang.reflect.Method; import android.view.View; import android.view.View.OnClickListener; public class EventListener implements OnClickListener { private Object handler;//执行自定义方法方法的对象 private String clickMethod;//自定义方法名 public EventListener(Object handler) { super(); this.handler = handler; } /** * * @param method * 方法名 * @return */ public EventListener click(String method) { this.clickMethod = method; return this; } @Override public void onClick(View v) { invokeClickMethod(handler, clickMethod, v); } /** * 用来执行自定义的方法 * @param o 执行自定义方法方法的对象 * @param methodName 自定义方法名 * @param parems 自定义方法 的参数(View v) * @return Object */ public static Object invokeClickMethod(Object o, String methodName, Object... parems) { if (o == null) { return null; } Method method = null; try { //通过反射获取指定方法名的Method对象 method = o.getClass().getDeclaredMethod(methodName, View.class); if (method != null) { //执行方法 return method.invoke(o, parems); } else { throw new ClickNotFindException("方法没有找到!" + methodName); } } catch (Exception e) { e.printStackTrace(); } return null; } }
package com.iotek.webservicedemo; public class ClickNotFindException extends RuntimeException { /** * */ private static final long serialVersionUID = 1L; private String msg; public ClickNotFindException(String msg) { super(); this.msg = msg; } @Override public void printStackTrace() { if (msg != null) { System.err.println(msg); } super.printStackTrace(); } }