java 注解 " />
当前位置: 代码迷 >> Android >> java 注解 
  详细解决方案

java 注解 

热度:274   发布时间:2016-04-28 05:57:52.0
android使用篇(四) 注解实现绑定控件实例化

在android使用篇(三) MVC模式中提到一个问题:

1) 视图层(View):一般采用XML文件进行界面的描述,使用的时候可以非常方便的引入,但是用xml编写了,又需要在Acitvity声明并且实例化,有点麻烦,考虑能否做一个类似注解实现匹配,或者写一个类获取xml的各个节点然后自动进行封装,当然,这只是个想法,以后再实现。

今天终于把这个想法实现了,使用IOC注解实现对activity中控件的实例化。

先普及一下java的反射机制和注解机制的知识:

以下引用大神的两篇文章:

JAVA反射机制  

java 注解 

完成后只需要: @ViewInject(id=R.id.btn1,click="btnClick") TextView btn1;  即可完成实例化,并添加点击事件

基本思路: 

一,public abstract class D3Activity extends Activity    写一个类继承Activity。

二,重写  setContentView   在此方法实现注解。

三,Field[] fields = activity.getClass().getDeclaredFields();    获取activity中的字段属性

四, field.getAnnotation(ViewInject.class);         获取字段的注解属性

五, field.set(activity,sourceView.findViewById(viewId));       实例化控件

大功告成,到此已实现了注解实现对android中activity和xml文件的实例化问题。

另外也可以实现注解对控件的事件添加,详细


分三个类实现:

实现注解类:

注解类可注入 id---对应xml的id,各种点击事件,可自己定义

@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME) public @interface ViewInject {	public int id() default 0;	public String click() default "";	public String longClick() default "";	public String itemClick() default "";	public String itemLongClick() default "";}


重写activity类,使用反射和注解实现实例化并加入事件:

public abstract class D3Activity extends Activity {	public void setContentView(int layoutResID) {		super.setContentView(layoutResID);		initInjectedView(this);	}	public void setContentView(View view, LayoutParams params) {		super.setContentView(view, params);		initInjectedView(this);	}	public void setContentView(View view) {		super.setContentView(view);		initInjectedView(this);	}		private void initInjectedView(Activity activity){		initInjectedView(activity, activity.getWindow().getDecorView());	}			private void initInjectedView(Object activity,View sourceView){		Field[] fields = activity.getClass().getDeclaredFields();   //获取字段		if(fields!=null && fields.length>0){			for(Field field : fields){				try {					field.setAccessible(true);   //设为可访问										if(field.get(activity)!= null )						continue;									ViewInject viewInject = field.getAnnotation(ViewInject.class);					if(viewInject!=null){												int viewId = viewInject.id();						if(viewId == 0)							viewId = getResources().getIdentifier(field.getName(), "id",getPackageName());						if(viewId == 0)							Log.e("D3Activity", "field "+ field.getName() + "not found");												//关键,注解初始化,相当于 backBtn = (TextView) findViewById(R.id.back_btn);					    field.set(activity,sourceView.findViewById(viewId));  					    //事件					    setListener(activity,field,viewInject.click(),Method.Click);						setListener(activity,field,viewInject.longClick(),Method.LongClick);						setListener(activity,field,viewInject.itemClick(),Method.ItemClick);						setListener(activity,field,viewInject.itemLongClick(),Method.itemLongClick);					}				} catch (Exception e) {					e.printStackTrace();				}			}		}	}		private void setListener(Object activity,Field field,String methodName,Method method)throws Exception{		if(methodName == null || methodName.trim().length() == 0)			return;				Object obj = field.get(activity);				switch (method) {			case Click:				if(obj instanceof View){					((View)obj).setOnClickListener(new EventListener(activity).click(methodName));				}				break;			case ItemClick:				if(obj instanceof AbsListView){					((AbsListView)obj).setOnItemClickListener(new EventListener(activity).itemClick(methodName));				}				break;			case LongClick:				if(obj instanceof View){					((View)obj).setOnLongClickListener(new EventListener(activity).longClick(methodName));				}				break;			case itemLongClick:				if(obj instanceof AbsListView){					((AbsListView)obj).setOnItemLongClickListener(new EventListener(activity).itemLongClick(methodName));				}				break;			default:				break;		}	}		public enum Method{		Click,LongClick,ItemClick,itemLongClick	}

事件类: 实现了 OnClickListener, OnLongClickListener, OnItemClickListener,OnItemLongClickListener ,可以自己扩展

public class EventListener implements OnClickListener, OnLongClickListener, OnItemClickListener,OnItemLongClickListener {	private Object handler;		private String clickMethod;	private String longClickMethod;	private String itemClickMethod;	private String itemLongClickMehtod;		public EventListener(Object handler) {		this.handler = handler;	}		public EventListener click(String method){		this.clickMethod = method;		return this;	}		public EventListener longClick(String method){		this.longClickMethod = method;		return this;	}		public EventListener itemLongClick(String method){		this.itemLongClickMehtod = method;		return this;	}		public EventListener itemClick(String method){		this.itemClickMethod = method;		return this;	}		public boolean onLongClick(View v) {		return invokeLongClickMethod(handler,longClickMethod,v);	}		public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {		return invokeItemLongClickMethod(handler,itemLongClickMehtod,arg0,arg1,arg2,arg3);	}		public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {				invokeItemClickMethod(handler,itemClickMethod,arg0,arg1,arg2,arg3);	}		public void onClick(View v) {				invokeClickMethod(handler, clickMethod, v);	}			private static Object invokeClickMethod(Object handler, String methodName,  Object... params){		if(handler == null) return null;		Method method = null;		try{   			method = handler.getClass().getDeclaredMethod(methodName,View.class);			if(method!=null)				return method.invoke(handler, params);				else				throw new RuntimeException("no such method:"+methodName);		}catch(Exception e){			e.printStackTrace();		}				return null;			}			private static boolean invokeLongClickMethod(Object handler, String methodName,  Object... params){		if(handler == null) return false;		Method method = null;		try{   			//public boolean onLongClick(View v)			method = handler.getClass().getDeclaredMethod(methodName,View.class);			if(method!=null){				Object obj = method.invoke(handler, params);				return obj==null?false:Boolean.valueOf(obj.toString());				}			else				throw new RuntimeException("no such method:"+methodName);		}catch(Exception e){			e.printStackTrace();		}				return false;			}				private static Object invokeItemClickMethod(Object handler, String methodName,  Object... params){		if(handler == null) return null;		Method method = null;		try{   			///onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3)			method = handler.getClass().getDeclaredMethod(methodName,AdapterView.class,View.class,int.class,long.class);			if(method!=null)				return method.invoke(handler, params);				else				throw new RuntimeException("no such method:"+methodName);		}catch(Exception e){			e.printStackTrace();		}				return null;	}			private static boolean invokeItemLongClickMethod(Object handler, String methodName,  Object... params){		if(handler == null) throw new RuntimeException("invokeItemLongClickMethod: handler is null :");		Method method = null;		try{   			///onItemLongClick(AdapterView<?> arg0, View arg1, int arg2,long arg3)			method = handler.getClass().getDeclaredMethod(methodName,AdapterView.class,View.class,int.class,long.class);			if(method!=null){				Object obj = method.invoke(handler, params);				return Boolean.valueOf(obj==null?false:Boolean.valueOf(obj.toString()));				}			else				throw new RuntimeException("no such method:"+methodName);		}catch(Exception e){			e.printStackTrace();		}				return false;	}}


到此已经完成了,只需要这样即可实例化:

public class MainActivity extends D3Activity {    	[email protected] EditText input;   //id和属性名相同,自动匹配	@ViewInject(id = R.id.input) EditText editText;     	@ViewInject(click="btnClick") TextView btn1,btn2,btn3;	    public void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.activity_main);      }  	public void btnClick(View v){    	    	switch (v.getId()) {		case R.id.btn1:			btn1.setText(editText.getText().toString());			Toast.makeText(getApplicationContext(), "111", Toast.LENGTH_SHORT).show();			break;				case R.id.btn2:			Toast.makeText(getApplicationContext(), "222", Toast.LENGTH_SHORT).show();			break;					case R.id.btn3:			Toast.makeText(getApplicationContext(), "333", Toast.LENGTH_SHORT).show();			break;		default:			break;		}    	    }    }

对应xml布局文件:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical" >        <EditText         android:id="@+id/input"        android:layout_width="fill_parent"        android:layout_height="wrap_content"                />    <TextView        android:id="@+id/btn1"        android:layout_marginTop="10dp"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="设置自己"         />	<TextView         android:id="@+id/btn2"        android:layout_marginTop="10dp"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="btn2"	    />			<TextView         android:id="@+id/btn3"        android:layout_marginTop="10dp"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="btn3"	    /></LinearLayout>


源码已经放在了github,有兴趣的可以去看看 :https://github.com/mozhenhau/injectAndroid.git


2楼what7abc7小时前
写得不错,很有用,学习了
1楼what7abc7小时前
是只有继承了activity的才能用注解绑定吗? adapter这些好像不能使用,如果能会用就更好了,但已经极大地方便了
  相关解决方案