otto源码解析

tips:

  • 接口的使用
public interface ThreadEnforcer {
    ThreadEnforcer ANY = new ThreadEnforcer() {
        public void enforce(Bus bus) {
        }
    };
    ThreadEnforcer MAIN = new ThreadEnforcer() {
        public void enforce(Bus bus) {
            if(Looper.myLooper() != Looper.getMainLooper()) {
                throw new IllegalStateException("Event bus " + bus + " accessed from non-main thread " + Looper.myLooper());
            }
        }
    };

    void enforce(Bus var1);
}
  • 判断是否为主线程:
if(Looper.myLooper() != Looper.getMainLooper()) {
                throw new IllegalStateException("Event bus " + bus + " accessed from non-main thread " + Looper.myLooper());
            }
  • 主要是Bus.java里面的代码:
    关键的方法有

public void register(Object object)
该方法的作用是查找object里面所有带有Produce和Subscribe注解的方法,并保存在Map中,并且会立即执行Produce注解的方法。

private static void loadAnnotatedMethods(Class<?> listenerClass) {
        HashMap subscriberMethods = new HashMap();
        HashMap producerMethods = new HashMap();
        Method[] arr$ = listenerClass.getDeclaredMethods();//将所有的方法都取出来
        int len$ = arr$.length;

        for(int i$ = 0; i$ < len$; ++i$) {
            Method method = arr$[i$];
            Class[] parameterTypes;
            Class eventType;
            if(method.isAnnotationPresent(Subscribe.class)) {  //自定义注解获取方法
                parameterTypes = method.getParameterTypes();
                if(parameterTypes.length != 1) {
                    throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation but requires " + parameterTypes.length + " arguments.  Methods must require a single argument.");
                }

                eventType = parameterTypes[0];
                if(eventType.isInterface()) {
                    throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation on " + eventType + " which is an interface.  Subscription must be on a concrete class type.");
                }

                if((method.getModifiers() & 1) == 0) {
                    throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation on " + eventType + " but is not \'public\'.");
                }

                Object methods = (Set)subscriberMethods.get(eventType);
                if(methods == null) {
                    methods = new HashSet();
                    subscriberMethods.put(eventType, methods);
                }

                ((Set)methods).add(method);
            } else if(method.isAnnotationPresent(Produce.class)) {
                parameterTypes = method.getParameterTypes();
                if(parameterTypes.length != 0) {
                    throw new IllegalArgumentException("Method " + method + "has @Produce annotation but requires " + parameterTypes.length + " arguments.  Methods must require zero arguments.");
                }

                if(method.getReturnType() == Void.class) {
                    throw new IllegalArgumentException("Method " + method + " has a return type of void.  Must declare a non-void type.");
                }

                eventType = method.getReturnType();
                if(eventType.isInterface()) {
                    throw new IllegalArgumentException("Method " + method + " has @Produce annotation on " + eventType + " which is an interface.  Producers must return a concrete class type.");
                }

                if((method.getModifiers() & 1) == 0) {
                    throw new IllegalArgumentException("Method " + method + " has @Produce annotation on " + eventType + " but is not \'public\'.");
                }

                if(producerMethods.containsKey(eventType)) {
                    throw new IllegalArgumentException("Producer for type " + eventType + " has already been registered.");
                }

                producerMethods.put(eventType, method);
            }
        }

        PRODUCERS_CACHE.put(listenerClass, producerMethods); //将所有带有Subscribe.class gen跟Produce.class 注解的方法保存下来
        SUBSCRIBERS_CACHE.put(listenerClass, subscriberMethods);
    }
  • public void post(Object event)
    发送事件event,根据之前注册过的object里面的方法,查找参数为event的Subscribe方法,并invoke该方法。这样就达到了post之后,调用对应Subscribe方法的目的。
 EventHandler(Object target, Method method) {
        if(target == null) {
            throw new NullPointerException("EventHandler target cannot be null.");
        } else if(method == null) {
            throw new NullPointerException("EventHandler method cannot be null.");
        } else {
            this.target = target;
            this.method = method;
            method.setAccessible(true);  //注意此处的开关是关闭java的安全检查机制,能提高反射的性能
            boolean prime = true;
            this.hashCode = (31 + method.hashCode()) * 31 + target.hashCode();
        }
    }
    
 public void handleEvent(Object event) throws InvocationTargetException {
        try {
            this.method.invoke(this.target, new Object[]{event});
        } catch (IllegalAccessException var3) {
            throw new AssertionError(var3);
        } catch (InvocationTargetException var4) {
            if(var4.getCause() instanceof Error) {
                throw (Error)var4.getCause();
            } else {
                throw var4;
            }
        }
    }
  • public void unregister(Object object)
    注销object,删除掉map中保存的object的方法,释放object,防止内存泄露。

总结:otto将所有带有注解的类存到map里面,包含了类,方法名,参数,等post或者有注解的时候,使用invoke 反射调用,所以都是使用了反射实现。

这里有一个小工具类,以后可以直接copy ,查找annotion

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.squareup.otto;

import com.squareup.otto.EventHandler;
import com.squareup.otto.EventProducer;
import com.squareup.otto.Produce;
import com.squareup.otto.Subscribe;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

final class AnnotatedHandlerFinder {
    private static final Map<Class<?>, Map<Class<?>, Method>> PRODUCERS_CACHE = new HashMap();
    private static final Map<Class<?>, Map<Class<?>, Set<Method>>> SUBSCRIBERS_CACHE = new HashMap();

    private static void loadAnnotatedMethods(Class<?> listenerClass) {
        HashMap subscriberMethods = new HashMap();
        HashMap producerMethods = new HashMap();
        Method[] arr$ = listenerClass.getDeclaredMethods();
        int len$ = arr$.length;

        for(int i$ = 0; i$ < len$; ++i$) {
            Method method = arr$[i$];
            Class[] parameterTypes;
            Class eventType;
            if(method.isAnnotationPresent(Subscribe.class)) {
                parameterTypes = method.getParameterTypes();
                if(parameterTypes.length != 1) {
                    throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation but requires " + parameterTypes.length + " arguments.  Methods must require a single argument.");
                }

                eventType = parameterTypes[0];
                if(eventType.isInterface()) {
                    throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation on " + eventType + " which is an interface.  Subscription must be on a concrete class type.");
                }

                if((method.getModifiers() & 1) == 0) {
                    throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation on " + eventType + " but is not \'public\'.");
                }

                Object methods = (Set)subscriberMethods.get(eventType);
                if(methods == null) {
                    methods = new HashSet();
                    subscriberMethods.put(eventType, methods);
                }

                ((Set)methods).add(method);
            } else if(method.isAnnotationPresent(Produce.class)) {
                parameterTypes = method.getParameterTypes();
                if(parameterTypes.length != 0) {
                    throw new IllegalArgumentException("Method " + method + "has @Produce annotation but requires " + parameterTypes.length + " arguments.  Methods must require zero arguments.");
                }

                if(method.getReturnType() == Void.class) {
                    throw new IllegalArgumentException("Method " + method + " has a return type of void.  Must declare a non-void type.");
                }

                eventType = method.getReturnType();
                if(eventType.isInterface()) {
                    throw new IllegalArgumentException("Method " + method + " has @Produce annotation on " + eventType + " which is an interface.  Producers must return a concrete class type.");
                }

                if((method.getModifiers() & 1) == 0) {
                    throw new IllegalArgumentException("Method " + method + " has @Produce annotation on " + eventType + " but is not \'public\'.");
                }

                if(producerMethods.containsKey(eventType)) {
                    throw new IllegalArgumentException("Producer for type " + eventType + " has already been registered.");
                }

                producerMethods.put(eventType, method);
            }
        }

        PRODUCERS_CACHE.put(listenerClass, producerMethods);
        SUBSCRIBERS_CACHE.put(listenerClass, subscriberMethods);
    }

    static Map<Class<?>, EventProducer> findAllProducers(Object listener) {
        Class listenerClass = listener.getClass();
        HashMap handlersInMethod = new HashMap();
        if(!PRODUCERS_CACHE.containsKey(listenerClass)) {
            loadAnnotatedMethods(listenerClass);
        }

        Map methods = (Map)PRODUCERS_CACHE.get(listenerClass);
        if(!methods.isEmpty()) {
            Iterator i$ = methods.entrySet().iterator();

            while(i$.hasNext()) {
                Entry e = (Entry)i$.next();
                EventProducer producer = new EventProducer(listener, (Method)e.getValue());
                handlersInMethod.put(e.getKey(), producer);
            }
        }

        return handlersInMethod;
    }

    static Map<Class<?>, Set<EventHandler>> findAllSubscribers(Object listener) {
        Class listenerClass = listener.getClass();
        HashMap handlersInMethod = new HashMap();
        if(!SUBSCRIBERS_CACHE.containsKey(listenerClass)) {
            loadAnnotatedMethods(listenerClass);
        }

        Map methods = (Map)SUBSCRIBERS_CACHE.get(listenerClass);
        if(!methods.isEmpty()) {
            Iterator i$ = methods.entrySet().iterator();

            while(i$.hasNext()) {
                Entry e = (Entry)i$.next();
                HashSet handlers = new HashSet();
                Iterator i$1 = ((Set)e.getValue()).iterator();

                while(i$1.hasNext()) {
                    Method m = (Method)i$1.next();
                    handlers.add(new EventHandler(listener, m));
                }

                handlersInMethod.put(e.getKey(), handlers);
            }
        }

        return handlersInMethod;
    }

    private AnnotatedHandlerFinder() {
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容