我正在使用greenrobot EventBus。
如果我有一个基类B和一个派生类D,并且都在函数f中订阅了事件E:
class E {}
class B {
@Subscribe
public f(E e) {}
}
class D extends B {
@Subscribe
public f(E e) {}
}
发送事件并且存在类型D的对象时会发生什么?
B.f()
和D.f()
都在对象上被调用D.f()
D.f()
被调用两次(每次注册一次)答案 0 :(得分:0)
对3.1.1版有效
假设您刚刚注册了D
的实例:
public class Scratch4 {
public static void main(String args[]) {
EventBus.getDefault()
.register(new D());
EventBus.getDefault()
.post(new E());
}
}
并且:
public class B {
@Subscribe
public void f(E e) {
System.out.println("IN B");
}
}
public class D extends B {
@Subscribe
public void f(E e) {
System.out.println("IN D");
}
}
然后main()
方法产生:
IN D
这是因为D覆盖了B中的方法void f(E e)
。
下面解释了为什么只一次调用该方法。
具体来说,当您注册订户时,将使用register
方法:
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
仅注册一种方法(D::f
)。
在后台,FindState
对象用于捕获查找。
随后,findState.checkAdd(method, eventType)
首先在SubscriberMethodFinder::findUsingReflectionInSingleClass
的{{1}}中运行(我们正在注册一个D,它在层次结构的底部),因此它返回true-这会导致添加D::f
方法来进行订阅通知。
然后它沿层次结构前进。
因此,第二次调用(使用D::f
)。这将返回false-使其不被添加到B::f
中。
此拒绝是因为findState
禁止在当前SubscribeMethodFinder::checkAddWithMethodSignature
中被子方法取代的方法成为候选方法:
FindState
下面解释了为什么仅调用子类的无效实现。
这是由于我们无法选择要在层次结构方法中选择哪种类型的事实而进一步实施的-如果我们调用被覆盖的方法,则将调用子级的版本。静态和运行时类型无关紧要。
private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {
methodKeyBuilder.setLength(0);
methodKeyBuilder.append(method.getName());
methodKeyBuilder.append('>').append(eventType.getName());
String methodKey = methodKeyBuilder.toString();
Class<?> methodClass = method.getDeclaringClass();
Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);
if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) {
// Only add if not already found in a sub class
return true;
} else {
// Revert the put, old class is further down the class hierarchy
subscriberClassByMethodKey.put(methodKey, methodClassOld);
return false;
}
}
收益:
public class Scratch4 {
public static void main(String args[]) throws Exception {
B b = new D();
Class<B> bClazz = B.class;
Method bClazzMethod = bClazz.getMethod("f", E.class);
bClazzMethod.invoke(b, new E());
}
}
如果要制作IN D
:
B
然后public class B {
@Subscribe
public void somethingThatIsNotF(E e) {
System.out.println("IN B");
}
}
方法将产生:
main()
我猜该顺序是由子对父顺序确定的(即IN D
IN B
,因此D extends B
排在第一位)。