Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix:issues 539 #615

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,9 @@ boolean checkAdd(Method method, Class<?> eventType) {
// Paranoia check
throw new IllegalStateException();
}
// Put any non-Method object to "consume" the existing Method
anyMethodByEventType.put(eventType, this);
}
// Put any non-Method object to "consume" the existing Method
anyMethodByEventType.put(eventType, this);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please explain how this change affects which subscriber method is detected? Won't that break existing code?

The code comment indicates that the put call should have been outside the if condition all along.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When duplicate register subscribe method, the method didn't wrap by FindState, so the next checkAddWithMethodSignature return false.

Here is an example:

we prepare 2 classes

open class EventBusBaseFragment : Fragment() {
    @Subscribe
    open fun subscribeMessage0(message: SendMessage) {
        Log.d("EventBusBaseFragment", "EventBusBaseFragment subscribeMessage0")
    }

    @Subscribe
    open fun subscribeMessage1(message: SendMessage) {
        Log.d("EventBusBaseFragment", "EventBusBaseFragment subscribeMessage1")
    }
}
open class SendFragment : EventBusBaseFragment() {
    @Subscribe
    override fun subscribeMessage0(message: SendMessage) {
        Log.d("SendFragment", "SendFragment subscribeMessage0")
    }

    @Subscribe
    override fun subscribeMessage1(message: SendMessage) {
        Log.d("SendFragment", "SendFragment subscribeMessage1")
    }
}

Also the key code

// /org/greenrobot/eventbus/SubscriberMethodFinder.java
boolean checkAdd(Method method, Class<?> eventType) {
    Object existing = anyMethodByEventType.put(eventType, method);
    if (existing == null) {
        return true;
    } else {
        if (existing instanceof Method) {
            if (!checkAddWithMethodSignature((Method) existing, eventType)) {
                throw new IllegalStateException();
            }
            anyMethodByEventType.put(eventType, this);
        }
        return checkAddWithMethodSignature(method, eventType);
    }
}
// /org/greenrobot/eventbus/SubscriberMethodFinder.java
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)) {
            return true;
        } else {
            subscriberClassByMethodKey.put(methodKey, methodClassOld);
            return false;
        }
    }
}

here is an analysis:

  1. first register : SendFragment#subscribeMessage0
    the key var in checkAddWithMethodSignature function is
methodClass:com.abelhu.androidstudy.ui.send.SendFragment
methodClassOld:null
methodKey:subscribeMessage0>com.abelhu.androidstudy.message.SendMessage

method insert into anyMethodByEventType directly

  1. second register: SendFragment#subscribeMessage1
    the key var in checkAddWithMethodSignature function is
methodClass:com.abelhu.androidstudy.ui.send.SendFragment
methodClassOld:null
methodKey:subscribeMessage1>com.abelhu.androidstudy.message.SendMessage

because the methodKey is different from first insert, so wrap method as FindState insert into anyMethodByEventType
2. third register : EventBusBaseFragment#subscribeMessage0
the key var in checkAddWithMethodSignature function is

methodClass:com.abelhu.androidstudy.ui.send.EventBusBaseFragment
methodClassOld:com.abelhu.androidstudy.ui.send.SendFragment
methodKey:subscribeMessage0>com.abelhu.androidstudy.message.SendMessage

method was inserted into anyMethodByEventType,
but in line 13 : **method not warp as FindState **, it was inserted directly!!!
3. fourth register: EventBusBaseFragment#subscribeMessage1
the key var in checkAddWithMethodSignature function is

methodClass:com.abelhu.androidstudy.ui.send.EventBusBaseFragment
methodClassOld:com.abelhu.androidstudy.ui.send.SendFragment
methodKey:subscribeMessage0>com.abelhu.androidstudy.message.SendMessage

eventType is equal, we get the third method, not FindState
when check by checkAddWithMethodSignature, it return false, so it throw an exception.


What we do

What we do is moving the code to wrap all method as FindState, so the check can pass.
Here is a detail analysis in chinese, refer

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@greenrobot-team
I don't know whether I express my meaning clearly.

return checkAddWithMethodSignature(method, eventType);
}
}
Expand Down