Android註解(annotation)實現綁定事件的原理
註解是一種很優雅的書寫方式,也是我們的代碼變的簡潔,更加快捷方便編寫代碼。下面以綁定onclick實踐為例闡述註解的原理。
1、定義Onclick註解類
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@BaseEvent(listenerSetter = "setOnclickListener", listenerType = View.OnClickListener.class, methodName = "onclick")public @interface OnClick { int[] values();}
BaseEvent用來制定需要綁定的方法名,事件的Listener,和綁定執行的方法名,BaseEvent的代碼如下
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface BaseEvent {Class listenerType();String listenerSetter();String methodName();}2、自訂的註解使用方式
@OnClick(R.id.download_btn) public void testUpload(View view) {}3、註解的解析(重點):
思路:可以通過我們的註解對象中取得添加onclick註解的方法(testUpload)反射方法對象,對這個對象進行事件的綁定。動態代理View事件中的OnclickLister,向代理對象中添加方法對象(testUpload)。方法的添加在EventListenerManager管理類中完成。
EventLisernerManager中定義動態代理類:
public static void addEventMethod(Method method,Annotation annotation,Object value,Object handler,ViewFinder finder){try{View view = finder.findViewByInfo(value);if(view!=null){BaseEvent baseEvent = annotation.annotationType().getAnnotation(BaseEvent.class);Class listenerType = baseEvent.listenerType();String listenerSetter = baseEvent.listenerSetter();String methodName = baseEvent.methodName();Object listener = listenerCache.get(value, listenerType);boolean addMethod = false;DynamicHandler dymicHandler = null;if(listener!=null){dymicHandler = (DynamicHandler) Proxy.getInvocationHandler(listener);addMethod = (handler.equals(dymicHandler.getHandler()));if(addMethod){dymicHandler.addMethod(methodName, method);}}if(!addMethod){dymicHandler = new DynamicHandler(handler);dymicHandler.addMethod(methodName, method);listener = Proxy.newProxyInstance(listenerType.getClassLoader(), new Class[]{listenerType},dymicHandler);listenerCache.put(value, listenerType, listener);}//setListenerMethod setterMethod = view.getClass().getMethod(listenerSetter, listenerType);setterMethod.invoke(view, listener);}}catch(Exception e){LogUtils.e(e.getMessage(),e);}}listener = Proxy.newProxyInstance(listenerType.getClassLoader(),new Class[]{listenerType},dymicHandler);動態代理了onClickListener。類中對代理對象進行的緩衝:
//緩衝代理對象public final static DoubleKeyValueMap, Object> listenerCache = null;
解析註解添加方法:
Method[] methods = handlerType.getDeclaredMethods();if(methods.length>0){for(Method method:methods){Annotation[] annotations = method.getDeclaredAnnotations();for(Annotation annotation : annotations){Class anType = annotation.annotationType();//拿到Annotation的Classif(anType.getAnnotation(BaseEvent.class)!=null){method.setAccessible(true);try{Method valueMethod = anType.getDeclaredMethod("values");Object values = valueMethod.invoke(annotation);int len = Array.getLength(values);if(len>0){for(int i=0;i 這裡可以拿到自訂method和註解本身。不太瞭解的可以研究下java的annotation的用法。由以上的方法的可以實現註解事件的綁定,可以自己定義事件的註解,優雅的開始你的代碼吧!