EventBus 안드로이드의 개발을위한 공통 프레임 워크, 그것은 칭찬의 디커플링 있다는 생각입니다
안드로이드 SDK의 약관 및 등록 둘 브로드 캐스트 리시버, 전송 이벤트, 안티 등록처럼, 당신은 이벤트의 우선 순위를 정의하고 점성 (끈적 끈적한) 이벤트를 지원할 수있는 특성에서, 단순한으로 EventBus를 사용하는 그리고 더 많은, 크로스 프로세스가 될 수 없습니다
안드로이드 SDK의 사실은, 메커니즘 --LocalBroadcastManager 브로드 캐스트 리시버 크로스 프로세스가없는, 그것은 단지 보내도 높은 유사성 EventBus 높은 수준의 보안을 가지고 있으며, 기존의 registerBroadcastReceiver에 비해이 과정에서 방송을 수신 할 수 있습니다
EventBus 기준 정보에 참조하시기 바랍니다 :
여기 EventBus 학습과 사용의 몇 군데의 가치가 생각과주의를 기록, 소스 코드와 함께 :
등록
- 어떤 방법으로 등록됩니다?
- 어떻게 같은 개체의 여러 등록을 할 것인가?
- 아니 어떻게 객체를 등록하는 주석 방법을 구독?
- 부모 클래스가 등록 된 객체가 주석을 구독하면 방법은 아직 등록됩니다?
- 자식 클래스 B는 상위 클래스 A 재미의 방법을 무시하면, 클래스 B의 자식 개체는 호출 할 때 호출? 어떤 방법으로 어떻게되는지 등록?
이러한 문제는, 우리는 레지스터 방법을 분석 할 필요가 :
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
// 1. 找 subscriber 中被需要被注册的方法
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
// 2. 注册这些方法
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
위의 첫 번째 포인트 코드에서 첫 모습;
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
// 缓存中取
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
if (ignoreGeneratedIndex) {
// 通过反射去找
subscriberMethods = findUsingReflection(subscriberClass);
} else {
// 通过 Subscriber Index 去找,这里如果没找到,也会通过反射去找
subscriberMethods = findUsingInfo(subscriberClass);
}
// 如果没有 找到被 Subscribe 注解的方法,抛出异常 ———— 问题 3
if (subscriberMethods.isEmpty()) {
throw new EventBusException("Subscriber " + subscriberClass
+ " and its super classes have no public methods with the @Subscribe annotation");
} else {
METHOD_CACHE.put(subscriberClass, subscriberMethods);
return subscriberMethods;
}
}
// 继续分析注册方法的查找过程findUsingReflection
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
findUsingReflectionInSingleClass(findState);
// 继续去 subscriberClass 的父类中找,但是这里有异常情况(几乎不会发生),往下看 ———— 问题 4
findState.moveToSuperclass();
}
return getMethodsAndRelease(findState);
}
// findState.moveToSuperclass();
void moveToSuperclass() {
if (skipSuperClasses) { // 异常情况,至于在哪里设置该标志位呢,继续往下看
clazz = null;
}
// ...
}
// 继续分析注册方法的查找过程 findUsingReflectionInSingleClass
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
// 先通过getDeclaredMethods查找,再通过getMethods查找
try {
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
methods = findState.clazz.getMethods();
// ...
// 问题 4 的异常情况,在 getDeclaredMethods 发生异常时,跳过父类的注册方法查找
findState.skipSuperClasses = true;
}
for (Method method : methods) {
int modifiers = method.getModifiers();
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 1) {
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
Class<?> eventType = parameterTypes[0];
if (findState.checkAdd(method, eventType)) {
// 方法被注册的条件: public,被 Subscribe 注解,参数列表只有1个参数(也就是事件类型) ———— 问题 1
ThreadMode threadMode = subscribeAnnotation.threadMode();
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
// 在设置了 strictMethodVerification 时,如果 Subscribe 注解的方法参数个数不是 1,抛出异常,默认 strictMethodVerification标志是false,可以通过 EventBusBuilder 设置
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException("@Subscribe method " + methodName +
"must have exactly 1 parameter but has " + parameterTypes.length);
}
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
// 在设置了 strictMethodVerification 时,如果被 Subscribe 注解的方法不是 public,抛出异常
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException(methodName +
" is a illegal @Subscribe method: must be public, non-static, and non-abstract");
}
}
}
두 번째 레지스터 방법 2 점을 보면 :
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class<?> eventType = subscriberMethod.eventType;
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
// 已经注册过了该 subscriber,再次注册抛出异常 ———— 问题 2
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
// ...
}
질문 5 위의 코드를 작성하지 않은 있지만, 사실, 질문 4에 대한 응답으로 포스트 호출시, 가입하고자하는 경우, 자격을 갖춘 부모 클래스가 등록됩니다 대답 된 호출에 의해, EventBus을 그렇게하는 방법입니다 호출 방법에 반사, 자연, 클래스의 방법을 달성하는 것입니다;
이벤트 트리거
- 대응하는있을 경우 게시, 등록 방법 EVENTTYPE 어떻게 찾을?
- 라인에서 이벤트 유형이 이벤트는 다형성 않는 호출 될 때?
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
Class<?> eventClass = event.getClass();
boolean subscriptionFound = false;
// 设置了 eventInheritance 标志,查找 eventType 的 父类 和 父接口 的对应的事件类型,eventInheritance 标志默认为 true ———— 问题 2
if (eventInheritance) {
List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
for (int h = 0; h < countTypes; h++) {
Class<?> clazz = eventTypes.get(h);
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
} else {
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
if (!subscriptionFound) {
// 没有找到对应 eventType 的注册方法,先打个日志
if (logNoSubscriberMessages) {
logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
}
// 如果设置了 sendNoSubscriberEvent 标志,post 一个 NoSubscriberEvent 事件 ———— 问题 1
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
post(new NoSubscriberEvent(this, event));
}
}
}
안티 등록
- 같은 개체를 여러 번 등록 취소, 또는 비 등록 된 오브젝트의 등록을 취소하는 방법?
public synchronized void unregister(Object subscriber) {
List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
for (Class<?> eventType : subscribedTypes) {
unsubscribeByEventType(subscriber, eventType);
}
typesBySubscriber.remove(subscriber);
} else {
// 没找到,就打了个日志 ———— 问题 1
logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}