/*
* Copyright (c) 2013. wyouflf (wyouflf@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lidroid.xutils.view;
import android.view.View;
import com.lidroid.xutils.util.LogUtils;
import com.lidroid.xutils.util.DoubleKeyValueMap;
import com.lidroid.xutils.view.annotation.event.EventBase;
import java.lang.annotation.Annotation;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
public class EventListenerManager {
private EventListenerManager() {
}
/**
* k1: viewInjectInfo
* k2: interface Type
* value: listener
*/
private final static DoubleKeyValueMap<ViewInjectInfo, Class<?>, Object> listenerCache =
new DoubleKeyValueMap<ViewInjectInfo, Class<?>, Object>();
public static void addEventMethod(
ViewFinder finder,
ViewInjectInfo info,
Annotation eventAnnotation,
Object handler,
Method method) {
try {
View view = finder.findViewByInfo(info);
if (view != null) {
EventBase eventBase = eventAnnotation.annotationType().getAnnotation(EventBase.class);
Class<?> listenerType = eventBase.listenerType();
String listenerSetter = eventBase.listenerSetter();
String methodName = eventBase.methodName();
boolean addNewMethod = false;
Object listener = listenerCache.get(info, listenerType);
DynamicHandler dynamicHandler = null;
if (listener != null) {
dynamicHandler = (DynamicHandler) Proxy.getInvocationHandler(listener);
addNewMethod = handler.equals(dynamicHandler.getHandler());
if (addNewMethod) {
dynamicHandler.addMethod(methodName, method);
}
}
if (!addNewMethod) {
dynamicHandler = new DynamicHandler(handler);
dynamicHandler.addMethod(methodName, method);
listener = Proxy.newProxyInstance(
listenerType.getClassLoader(),
new Class<?>[]{listenerType},
dynamicHandler);
listenerCache.put(info, listenerType, listener);
}
Method setEventListenerMethod = view.getClass().getMethod(listenerSetter, listenerType);
setEventListenerMethod.invoke(view, listener);
}
} catch (Throwable e) {
LogUtils.e(e.getMessage(), e);
}
}
public static class DynamicHandler implements InvocationHandler {
private WeakReference<Object> handlerRef;
private final HashMap<String, Method> methodMap = new HashMap<String, Method>(1);
public DynamicHandler(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();
if (handler != null) {
String methodName = method.getName();
method = methodMap.get(methodName);
if (method != null) {
return method.invoke(handler, args);
}
}
return null;
}
}
}