3

I'm attempting to subscribe to an EventBus event. Due to the parent class not existing in API level 23 and below, I'm in a situation where I need to conditionally subscribe to said event.

I realize that, through the use of build variants, it is possible to get around this, but I'm curious if there's a more elegant solution. The @RequiresApi annotation doesn't seem to have any effect (maybe stacking annotations doesn't work the way I expect it to).

Some simplified sample code:

class MyClass : OtherClass() {
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onSomeEvent(someEvent: SomeEvent) {
        // do some stuff
    }
}

Assuming OtherClass() is only available in API level 24+, the app will hang on the splash screen on lower API levels right after Dalvik or the ART realizes that the generated EventBusIndex references a broken class.

michael
  • 463
  • 3
  • 9
  • `@RequiresApi` has no effect on runtime behavior -- it is there for Lint to be smarter about what it warns you about. Do you get this crash even if you do not call `register()` to register your subscriber? – CommonsWare Jul 22 '19 at 18:48
  • @CommonsWare Even after commenting out any `register()`/`unregister()` calls it will still hang on the splash screen due to the EventBusIndex. – michael Jul 22 '19 at 18:51
  • OK, if you disable the EventBusIndex annotation processor, and do not register this subscriber on the older device, does it work? – CommonsWare Jul 22 '19 at 19:06
  • @CommonsWare Disabling the EventBus annotation processor (and thereby also having to disable adding the index to the default event bus) will, as expected, fix the issue. – michael Jul 22 '19 at 19:16
  • There's nothing stopping EventBus' annotation processor from either paying attention to something like `@RequiresApi` or having their own similar annotation property. My guess is that would require a feature request and some work on their part. – CommonsWare Jul 22 '19 at 19:17
  • @CommonsWare Yeah, figures. Do you know of any way to get around this in the meantime without needing to create more build variants? – michael Jul 22 '19 at 19:19
  • 1
    You could refactor your code such that your subscriber is not extending a class that may or may not exist (e.g., have `MyClass` hold something that is the subscriber, rather than being the subscriber itself). Or you could disable the annotation processor. Other than those two options and the build variant solution, I don't have any great ideas -- sorry! – CommonsWare Jul 22 '19 at 19:21

1 Answers1

1

You could try to tweak MyClass somewhat to move the subscription to another object:

class MyClass : OtherClass() {
    val subber = Subber()

    fun onSomeEventForRealz(someEvent: SomeEvent) {
        // do some stuff
    }

    inner class Subber {
        @Subscribe(threadMode = ThreadMode.MAIN)
        fun onSomeEvent(someEvent: SomeEvent) = onSomeEventForRealz(someEvent)
    }
}

You would also need to adjust your subscribe() and unsubscribe() calls to pass in subber instead of the MyClass instance itself.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491