Android xUtils框架(二) ViewUtils

框架地址:https://github.com/wyouflf/xUtils

作用:

  • 完全注解方式就可以进行UI绑定和事件绑定。
  • 无需findViewById和setClickListener等。

UI绑定:

@ContentView(R.layout.view_acti) //setContentView 注解在activity的声明上方

@ViewInject(R.id.lv_test) //反射view  注解在一个view声明上

@ResInject(id=R.string.app_name, type=ResType.String) //资源反射  ResType中定义了res/values下的一些资源类型

@PreferenceInject("key") //注解在一个Preference组件上 value为它的key值

ViewUtils.inject(activity);//通过反射,查找相应view的,并初始化


事件绑定

@OnClick(R.id.btn_test) //将一个自定义的方法绑定到一个view的事件上

package com.lidroid.xutils.view.annotation 包下,定义了一些常见的事件,它们有个特点,即都只有一个内部实现方法


事件绑定并执行的流程分析

	
        @ViewInject(R.id.btn_test)
	private Button mButton;
	
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		ViewUtils.inject(this);
		
		mButton.setText(label);
		
		Method testButtonClickMethod;
		try {
			testButtonClickMethod = this.getClass().getMethod("testButtonClick", View.class);
			MyOnClick onClick = testButtonClickMethod.getAnnotation(MyOnClick.class);
			MyEventBase eventBase = onClick.annotationType().getAnnotation(MyEventBase.class);
	        Class<?> listenerType = eventBase.mlistenerType();//View.OnClickListener.class
	        String listenerSetter = eventBase.mlistenerSetter();//setOnClickListener
	        String methodName = eventBase.mmethodName();//onClick
	        
	        MyDynamicHandler dynamicHandler = new MyDynamicHandler(ViewActivity.this);
	        dynamicHandler.addMethod(methodName, testButtonClickMethod);//将实质要调用的method加入到handler内部的map集中
	        Object listener = Proxy.newProxyInstance(//动态代理
	                listenerType.getClassLoader(),
	                new Class<?>[]{listenerType},
	                dynamicHandler);
	        Method setEventListenerMethod = mButton.getClass().getMethod(listenerSetter, listenerType);//setOnClickListener-method
	        /*
	         * onCreate()直接执行的:
	         * 		首先这里调用的是:mButton.setOnClickListener(listener);
	         * 		listener传进代理对象
	         * 	  		 注意:dynamicHandler的invoke
	         * 
	         * touch过后:
	         * 		dispatchTouchEvent的一次action-down和action-up之后,触发view的onClick-event
	         *		OnClickListener已经设置为代理对象listener了
	         *		就会调用listener对应的处理器dynamicHandler.invoke()
	         *		invoke中:最终执行testButtonClick方法
	         * 
	         */
	        setEventListenerMethod.invoke(mButton, listener); 
	        
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
        
	}
        @MyOnClick(R.id.btn_test) 
	public void testButtonClick(View v) {
		LogUtil.print("点击了button");
	}
	
	@Target(ElementType.ANNOTATION_TYPE)
	@Retention(RetentionPolicy.RUNTIME)
	public @interface MyEventBase {
	    Class<?> mlistenerType();

	    String mlistenerSetter();

	    String mmethodName();
	}
	
	@Target(ElementType.METHOD)
	@Retention(RetentionPolicy.RUNTIME)
	@MyEventBase(
        mlistenerType = View.OnClickListener.class,
        mlistenerSetter = "setOnClickListener",
        mmethodName = "onClick")
	private static @interface MyOnClick {
		 int[] value();
		 int[] parentId() default 0;
	}
	
	public class MyDynamicHandler implements InvocationHandler {
		private WeakReference<Object> handlerRef;
		private final HashMap<String, Method> methodMap = new HashMap<String, Method>(1);

		public MyDynamicHandler(Object handler) {
			this.handlerRef = new WeakReference<Object>(handler);
		}

		public void addMethod(String name, Method method) {
			methodMap.put(name, method);
		}

		public Object getHandler() {
			return handlerRef.get();
		}

		public void setHandler(Object handler) {
			this.handlerRef = new WeakReference<Object>(handler);
		}

		@Override
		public Object invoke(Object proxy, Method method, Object[] args)
				throws Throwable {
			Object handler = handlerRef.get();//viewActivity
			if (handler != null) {
				String methodName = method.getName();
				System.out.println("InvocationHandler.invoke--methodName:" + methodName);
				method = methodMap.get(methodName);
				if (method != null) {
					return method.invoke(handler, args);
				}
			}
			return null;
		}
	}
	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		System.out.println("dispatch");
		return super.dispatchTouchEvent(ev);
	}

类似的,其他一些事件都会像上面这样用动态代理的形式,来绑定你使用事件注解的方法和对应事件。


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。