Afinal的FinalActivity的注解学习笔记

在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;

	}
}

下面是 ClickNotFindException类

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();
	}


}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值