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

Subclass parent class subscribers define multiple sets of the same subscription method to report IllegalStateException #539

Closed
kakaxicm opened this issue Jul 17, 2018 · 2 comments

Comments

@kakaxicm
Copy link

kakaxicm commented Jul 17, 2018

The parent class Activity code is as follows:

public class BaseActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);
    }

    @Override
    public void onStop() {
        super.onStop();
        EventBus.getDefault().unregister(this);
    }
    //下面两个是订阅者方法
    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true, priority = 100)
    public void onMessageEvent(MsgEvent event) {
        Toast.makeText(this, "BaseActivity"+event.getValue(), Toast.LENGTH_LONG).show();
    }

    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true, priority = 101)
    public void onMessageEvent1(MsgEvent event) {
        Toast.makeText(this, "BaseActivity"+event.getValue()+"11111", Toast.LENGTH_LONG).show();
    }
}

子类如下:

public class MainActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    //下面的两个订阅方法和父类的相同,也就是说对EB框架而言methodKey是相同的
    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true, priority = 100)
    public void onMessageEvent(MsgEvent event) {
        Toast.makeText(this, event.getValue(), Toast.LENGTH_LONG).show();
    }

    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true, priority = 101)
    public void onMessageEvent1(MsgEvent event) {
        Toast.makeText(this, event.getValue()+"11111", Toast.LENGTH_LONG).show();
    }

    /**
     * 发送事件
     * @param view
     */
    public void onSend(View view) {
        //构造事件消息,发送
        MsgEvent event = new MsgEvent("haha");
        EventBus.getDefault().post(event);
    }
}

CN: 我的目的是想测试子类的订阅方法是否会覆盖父类的订阅方法,如果注释掉父类的一个订阅方法,可以正常运行,子类的订阅方法也覆盖了父类同名的订阅方法,(源码FindState类里面的校验机制也是如此,子类的订阅方法覆盖同名的父类订阅方法),但是对多组相同的订阅方法而言,跟进代码,会执行到下面的方法的所标注的崩溃位置,这里添加一组相同订阅方法会通过位置1代码返回,不会崩溃,当第二组相同key的Method对象添加进来时就会走到方法签名校验了,抛出IllegalStateException,而且崩溃原因很难查到。

EN: My purpose is to test whether the subclass's subscription method will override the parent's subscription method. If you comment out a parent class's subscription method, it can run normally. The subclass's subscription method also overrides the parent class's subscription method with the same name. The same is true for the validation mechanism in the source FindState class. The subclass's subscription method overrides the parent class subscription method of the same name. However, for multiple sets of the same subscription method, the follow-up code will be executed to the following method. In the crash location, adding a set of the same subscription method here will be returned by the position 1 code, and will not crash. When the second set of Method objects of the same key are added, it will go to the method signature check, throw an IllegalStateException, and the cause of the crash. Hard to find.

 boolean checkAdd(Method method, Class<?> eventType) {
            // 2 level check: 1st level with event type only (fast), 2nd level with complete signature when required.
            // Usually a subscriber doesn't have methods listening to the same event type.
            Object existing = anyMethodByEventType.put(eventType, method);
            if (existing == null) {
                return true;
            } else {
                if (existing instanceof Method) {
                    if (!checkAddWithMethodSignature((Method) existing, eventType)) {
                        // Paranoia check
                       //《=========崩溃位置========》
                        throw new IllegalStateException();
                    }
                    // Put any non-Method object to "consume" the existing Method
                    anyMethodByEventType.put(eventType, this);
                }
                return checkAddWithMethodSignature(method, eventType);//位置1
            }
        }

我可以理解这种设计的初衷是限制订阅者方法最好定义到子类,但是项目难免存在大量的类覆写,这样是不是增加了维护成本?请问大神们在大型项目中如歌规避这个限制所带来的崩溃?还是说这是这个框架的bug?

@greenrobot-team greenrobot-team changed the title 子类父类订阅者定义多组同样的订阅方法报IllegalStateException异常 Subclass parent class subscribers define multiple sets of the same subscription method to report IllegalStateException Aug 27, 2018
@greenrobot-team
Copy link
Collaborator

The @Subscribe annotation should only be added to the subclass.

Closing. Please re-open if your question was not answered.
-ut

@o0starshine0o
Copy link

The issue has been fixed, please merge my request, thx.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants