灵感来源:多线程模块:http://blog.mcxiaoke.com/
下面是两个类,直接copy过去run就好了,接下来说下里面要注意的一些坑
首先,创建一个注解,用来为后续的方法筛选做准备,然后创建一个类A拥有register,post,unregister三个方法,顺便给上注解;
然后创建一个类B,构造函数就是放入A,通过一个方法findMethod将A中的所有方法都接受,这是最基础的,然后通过筛选将注解过的方法进行整合返回一个Set因为Set里面不允许重复;
在A中的register方法中运行B.findMethod(),这样就OK了,然后在A的post方法中随便传一个对象C,和返回的Set方法中的参数做匹配,然后用method.invoke方法将C传入到对应的方法并执行;
完结撒花!!!!!
public class Bus {
private static classSingletonHolder {
static finalBusINSTANCE=newBus();
}
public staticBus getDefault() {
returnSingletonHolder.INSTANCE;
}
privateMap>mMethodMap=newWeakHashMap>();
public voidregister(finalObject target) {
if(mMethodMap.containsKey(target)) {
System.err.println("target "+ target +" is already registered");
return;
}
Set methods = Helper.findAnnotatedMethods(target.getClass(),BusReceiver.class);
if(methods ==null|| methods.isEmpty()) {
return;
}
mMethodMap.put(target, methods);
}
public voidunregister(finalObject target) {
System.out.println("unregister() target="+ target);
mMethodMap.remove(target);
}
public void post(Object event) {
finalClass eventClass = event.getClass();
intsentCount =0;
for(Map.Entry> entry :mMethodMap.entrySet()) {
finalObject target = entry.getKey();
finalSet methods = entry.getValue();
if(methods ==null|| methods.isEmpty()) {
continue;
}
for(Method method : methods) {
Class parameterClass = method.getParameterTypes()[0];
if(parameterClass.isAssignableFrom(eventClass)) {
try{
System.out.println("post event to "
+ target +"."+ method.getName());
method.invoke(target, event);
sentCount++;
}catch(IllegalAccessException e) {
e.printStackTrace();
}catch(InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
if(sentCount ==0) {
System.err.println("no receiver found for event: "+ event);
}
}
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public@interfaceBusReceiver{
}
public classBusDemo {
public static voidmain(String[] args) {
finalBusDemo demo =newBusDemo();
Bus bus = Bus.getDefault();
bus.register(demo);
bus.post(newTom());
// bus.post(new Object());
// bus.post("SomeEvent");
// bus.post(12345);
// bus.post(new Exception("Error"));
}
@BusReceiver
public voidonReceiveRunnableNotPost(Runnable event) {
System.out.println("onReceiveRunnableNotPost() event="+ event);
}
@BusReceiver
public voidonObjectEvent(Object event) {
System.out.println("onObjectReceive() event="+ event);
}
@BusReceiver
public voidonExceptionEvent(Exception event) {
System.out.println("onExceptionEvent() event="+ event);
}
@BusReceiver
public voidonStringReceive(String event) {
System.out.println("onStringReceive() event="+ event);
}
@BusReceiver
public voidonInteger(Integer event) {
System.out.println("onInteger() event="+ event);
}
@BusReceiver
public voidonPerson(Person event) {
event.output();
}
}
final classHelper {
private static booleanshouldSkipClass(finalClass clazz) {
finalString clsName = clazz.getName();
returnObject.class.equals(clazz)
|| clsName.startsWith("java.")
|| clsName.startsWith("javax.")
|| clsName.startsWith("android.")
|| clsName.startsWith("com.android.");
}
private static booleanisAnnotatedMethod(finalMethod method,
finalClass annotation) {
// must has annotation
if(!method.isAnnotationPresent(annotation)) {
return false;
}
// must be public
if(!Modifier.isPublic(method.getModifiers())) {
return false;
}
// must not static
if(Modifier.isStatic(method.getModifiers())) {
return false;
}
// must not be volatile
// fix getDeclaredMethods bug, if method in base class,
// it returns duplicate method,
// one is normal, the other is the same but with volatile modifier
if(Modifier.isVolatile(method.getModifiers())) {
return false;
}
// must has only one parameter
if(method.getParameterTypes().length!=1) {
return false;
}
return true;
}
public staticSet findAnnotatedMethods(finalClass type,
finalClass annotation) {
Class clazz = type;
finalSet methods =newHashSet();
while(!shouldSkipClass(clazz)) {
finalMethod[] allMethods = clazz.getDeclaredMethods();
for(finalMethod method : allMethods) {
if(isAnnotatedMethod(method, annotation)) {
methods.add(method);
}
}
// search more methods in super class
clazz = clazz.getSuperclass();
}
returnmethods;
}
public static voiddumpMethod(finalMethod method) {
finalStringBuilder builder =newStringBuilder();
builder.append("------------------------------\n");
builder.append("MethodName: ").append(method.getName()).append("\n");
builder.append("ParameterTypes:{");
for(Class cls : method.getParameterTypes()) {
builder.append(cls.getName()).append(", ");
}
builder.append("}\n");
builder.append("GenericParameterTypes:{");
for(Type cls : method.getGenericParameterTypes()) {
builder.append(cls.getClass()).append(", ");
}
builder.append("}\n");
builder.append("TypeParameters:{");
for(TypeVariable cls : method.getTypeParameters()) {
builder.append(cls.getName()).append(", ");
}
builder.append("}\n");
builder.append("DeclaredAnnotations:{");
for(Annotation cls : method.getDeclaredAnnotations()) {
builder.append(cls).append(", ");
}
builder.append("}\n");
builder.append("Annotations:{");
for(Annotation cls : method.getAnnotations()) {
builder.append(cls).append(", ");
}
builder.append("}\n");
builder.append("ExceptionTypes:{");
for(Class cls : method.getExceptionTypes()) {
builder.append(cls.getName()).append(", ");
;
}
builder.append("}\n");
builder.append("ReturnType: ").append(method.getReturnType());
builder.append("\nGenericReturnType: ").append(method.getGenericReturnType());
builder.append("\nDeclaringClass: ").append(method.getDeclaringClass());
builder.append("\n");
System.out.println(builder.toString());
}
}