我使用eventbus传递点击事件,出现了订阅者执行俩次的问题
传递的参数中的对象有一个字段是list
我打断点看,发送事件的位置只发送了一遍,但是接收事件的位置出现了俩次
我收到三次。。
@ccclll1990 问题的原因找到了,是fragment的复用引起的,如果fragment要复用就要进行特殊的处理
还有种情况,如果传的参数是Map类型,还会执行N次(N>5),看源码是Map继承自多个类的子类,然后符合这些类的响应,自然就执行多次了,解决办法是只传基础类型数据,int,boolean,string及数组类型,或者改源码
@Creky 我也遇见这个问题了,我直接传递父类的直接子类就解决了这个问题,谢谢了哈。
@chengzhijun0706 你好,我也是fragment出现的,怎么处理的?
@chengzhijun0706 你好,我也是fragment出现的,怎么处理的?
如果fragment存在复用的场景需要特殊处理,我是这样处理的,仅供参考(前提时发布事件的时候能够取到订阅的对象) 需要对源码进行改动 为了区分不同的fragment的对象,我想把fragment对象的hash作为tag,进行事件注册。 但是在注解中又只能使用常量。所以想了一个迂回的办法。 1.注解的时候用参数标识这个事件注册的时候需要把对象object的hash加到tag中, 2.在EventBus注册的时候识别这个参数,并把object的hash加到tag中 3.事件发布的时候将fragment对象的hash手动添加到tag中
1.首先Subscriber注解中增加一个方法
/**
*/
boolean registerWithObjectHash() default false;
2.Eventbus注册的时候判断该参数,并注册的时候特殊处理
浏览代码容易找到Eventus注册的方法是在SubsciberMethodHunter. findSubcribeMethods 的方法中,对该方法略作改动
/**
* 查找订阅对象中的所有订阅函数,订阅函数的参数只能有一个.找到订阅函数之后构建Subscription存储到Map中
*
* @param subscriber 订阅对象
* @return
*/
public void findSubcribeMethods(Object subscriber) {
if (mSubcriberMap == null) {
throw new NullPointerException("the mSubcriberMap is null. ");
}
Class<?> clazz = subscriber.getClass();
// 查找类中符合要求的注册方法,直到Object类
while (clazz != null && !isSystemCalss(clazz.getName())) {
final Method[] allMethods = clazz.getDeclaredMethods();
for (int i = 0; i < allMethods.length; i++) {
Method method = allMethods[i];
// 根据注解来解析函数
Subscriber annotation = method.getAnnotation(Subscriber.class);
if (annotation != null) {
// 获取方法参数
Class<?>[] paramsTypeClass = method.getParameterTypes();
// 订阅函数只支持一个参数
if (paramsTypeClass != null && paramsTypeClass.length == 1) {
Class<?> paramType = convertType(paramsTypeClass[0]);
EventType eventType
if(annotation.registerWithObjectHash()){
eventType = new EventType(paramType, annotation.tag()+subscriber.toString());
}else{
eventType = new EventType(paramType, annotation.tag());
}
TargetMethod subscribeMethod = new TargetMethod(method, eventType,
annotation.mode());
subscibe(eventType, subscribeMethod, subscriber);
}
}
} // end for
// 获取父类,以继续查找父类中符合要求的方法
clazz = clazz.getSuperclass();
}
}
example:
注册时
class Fragment
...
@Subscriber(tag="testevent",registerWithObjectHash=true)
public void test(String test){
}
发布事件时
post("","testevent"+fragment.toString)
@xilost 我用了一个比较笨的办法,就是在你传递的对象中携带有一个区分页面的字段,在接受的地方判断这个字段的值是否和本页面相等就好了