Аннотации Android и EventBus

У меня есть аннотированная активность в библиотеке, которая является подписчиком события EventBus из той же библиотеки. Выглядит это примерно так, сильно упрощенно:

@EActivity(resName = "activity_foo")
public class Foo extends Activity {

    public void onEvent(BarEvent event){
        doSomething();
    }
}

Это должно работать в соответствии с этим:

http://timnew.me/blog/2014/09/14/otto-and-android-annotations-compatibility-issue-analysis/

Но на самом деле он возвращается с этой ошибкой:

Невозможно начать действие... de.greenrobot.event.EventBusException: класс подписчика com.foo.bar.activities.Foo_ не имеет общедоступных методов, называемых onEvent

Кажется, EventBus не смотрит в родительский класс. Я предполагаю, что аннотация @Subscribe, о которой все говорят, есть только в Guava и Otto, но не в EventBus. В сети никто не говорит о проблемах совместимости между AA и Eventbus, так что я, должно быть, что-то упускаю.

Как я могу заставить это работать?

EventBus: 2.4

AA: 3.2

ИЗМЕНИТЬ:

После ответа WonderCsabo я обновил EventBus до бета-версии 3.0 (включая аннотации подписки) и AA до 3.3.1, и проблема исчезла, но есть еще одна:

   java.lang.NoSuchFieldError
            at libcore.reflect.AnnotationAccess.decodeValue(AnnotationAccess.java:688)
            at libcore.reflect.AnnotationAccess.getDefaultValue(AnnotationAccess.java:361)
            at java.lang.reflect.Method.getDefaultValue(Method.java:327)
            at libcore.reflect.AnnotationFactory.getElementsDescription(AnnotationFactory.java:75)
            at libcore.reflect.AnnotationFactory.<init>(AnnotationFactory.java:112)
            at libcore.reflect.AnnotationFactory.createAnnotation(AnnotationFactory.java:94)
            at libcore.reflect.AnnotationAccess.toAnnotationInstance(AnnotationAccess.java:666)
            at libcore.reflect.AnnotationAccess.toAnnotationInstance(AnnotationAccess.java:641)
            at libcore.reflect.AnnotationAccess.getDeclaredAnnotation(AnnotationAccess.java:170)
            at java.lang.reflect.Method.getAnnotation(Method.java:301)
            at de.greenrobot.event.n.b(SourceFile:133)
            at de.greenrobot.event.n.a(SourceFile:79)
            at de.greenrobot.event.c.a(SourceFile:135)
            at com.babestudios.lib.lq.activities.f.onStart(SourceFile:515)
            at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1236)
            at android.app.Activity.performStart(Activity.java:6006)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2288)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
            at android.app.ActivityThread.access$800(ActivityThread.java:151)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
     Caused by: java.lang.NoSuchFieldException: PostThread
            at java.lang.Class.getDeclaredField(Class.java:890)
            at libcore.reflect.AnnotationAccess.decodeValue(AnnotationAccess.java:685)
            at libcore.reflect.AnnotationAccess.getDefaultValue(AnnotationAccess.java:361)
            at java.lang.reflect.Method.getDefaultValue(Method.java:327)
            at libcore.reflect.AnnotationFactory.getElementsDescription(AnnotationFactory.java:75)
            at libcore.reflect.AnnotationFactory.<init>(AnnotationFactory.java:112)
            at libcore.reflect.AnnotationFactory.createAnnotation(AnnotationFactory.java:94)
            at libcore.reflect.AnnotationAccess.toAnnotationInstance(AnnotationAccess.java:666)
            at libcore.reflect.AnnotationAccess.toAnnotationInstance(AnnotationAccess.java:641)
            at libcore.reflect.AnnotationAccess.getDeclaredAnnotation(AnnotationAccess.java:170)
            at java.lang.reflect.Method.getAnnotation(Method.java:301)
            at de.greenrobot.event.n.b(SourceFile:133)
            at de.greenrobot.event.n.a(SourceFile:79)
            at de.greenrobot.event.c.a(SourceFile:135)
            at com.babestudios.lib.lq.activities.f.onStart(SourceFile:515)
            at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1236)
            at android.app.Activity.performStart(Activity.java:6006)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2288)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
            at android.app.ActivityThread.access$800(ActivityThread.java:151)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

И я заметил, что обе проблемы (отсутствующий onEvent и теперь PostThread - проблема только на релизной версии. Я использую ProGuard с рекомендуемыми исключениями для EventBus и AA).

ИЗМЕНИТЬ 2:

я добавил

-keep class de.greenrobot.** {*;}

и вроде работает.


person Herrbert74    schedule 22.06.2015    source источник
comment
похоже, вы пытаетесь вызвать класс Foo_ вместо класса Foo.   -  person Sergey Shustikov    schedule 23.06.2015
comment
Да, в этом суть АА. Это сгенерированный подкласс Foo.   -  person Herrbert74    schedule 23.06.2015
comment
Это сработало для вас? Я пытаюсь использовать EventBus 3.0 с AA, но пока это не сработало... EventBus не вызывает мой метод подписки, хотя я отправил сообщение =/   -  person Cícero Moura    schedule 19.12.2016
comment
Это все еще работает для меня. Я использую шину событий: 3.0.0 и АА: 3.3.2. Мне пришлось изменить de.greenrobot:eventbus на org.greenrobot.eventbus.   -  person Herrbert74    schedule 20.12.2016


Ответы (4)


У вас есть три варианта:

  • Используйте Отто. Он также имеет ту же проблему, с которой вы столкнулись с EventBus, однако AndroidAnnotations имеет специальную интеграцию Otto, которая решает эту проблему.
  • Если вы хотите использовать EventBus, вы можете попробовать экспериментальную версию, в которой нет проблема как 2.4.0. Это также лучше, поскольку основано на аннотациях, а не на именовании методов, не говоря уже об огромном приросте производительности за счет дополнительного процессора аннотаций EventBus. Но это все еще в бета-версии.
  • Или вы можете использовать EventBus 2.3.0, у которого нет проблем с 2.4.0.

Кстати, вы должны обновить Android Annotations до последней версии 3.3.1.

person WonderCsabo    schedule 22.06.2015

У меня есть аннотации EventBus, работающие с:

# Ensure annotations are kept for runtime use.
-keepattributes *Annotation*
# Don't remove any GreenRobot classes
-keep class de.greenrobot.** {*;}
# Don't remove any methods that have the @Subscribe annotation
-keepclassmembers class ** {
    @de.greenrobot.event.Subscribe <methods>;
}

Обратите внимание, что это также гарантирует, что имена ваших методов по-прежнему запутываются.

person deive    schedule 22.07.2015

Если кто-то все еще сталкивается с этой ошибкой, с EventBus 3.0 пакет был переименован (org вместо de и eventbus вместо event), поэтому правильная конфигурация proguard:

## GreenRobot EventBus specific rules ##
# http://greenrobot.org/eventbus/documentation/proguard/

-keepattributes *Annotation*

-keepclassmembers class ** {
    @org.greenrobot.eventbus.Subscribe <methods>;
}

-keep enum org.greenrobot.eventbus.ThreadMode { *; }

# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
    <init>(java.lang.Throwable);
}

как описано на их сайте.

person Alessio    schedule 19.02.2016

ОБНОВЛЕНИЕ

Кажется, это не правильный ответ. Исключение все равно выбрасывается.

Исходный ответ

Начиная с EventBus 3, вы можете отключить исключение подписчика, вызвав throwSubscriberException(false).

Вызывая это в своем классе приложения, вы можете отключить это исключение для своей шины событий по умолчанию.

EventBus.builder().throwSubscriberException(false).installDefaultEventBus();
person cybergen    schedule 01.03.2016