Skip to content

Generated indexes do not work on API <= 8 #312

@nikclayton

Description

@nikclayton

tl;dr: Eventbus should automatically ignore the generated index on devices <= API 8, and probably log a warning message.

findSubscriberMethods looks for methods using either findUsingReflection or findUsingInfo depending on whether the generated index is provided.

    List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
        if (subscriberMethods != null) {
            return subscriberMethods;
        }

        if (ignoreGeneratedIndex) {
            subscriberMethods = findUsingReflection(subscriberClass);
        } else {
            subscriberMethods = findUsingInfo(subscriberClass);
        }
        if (subscriberMethods.isEmpty()) {
            throw new EventBusException("Subscriber " + subscriberClass
                    + " and its super classes have no public methods with the @Subscribe annotation");
        } else {
            METHOD_CACHE.put(subscriberClass, subscriberMethods);
            return subscriberMethods;
        }
    }

If there's a generated index then findUsingInfo calls getSubscriberMethods which calls getSubscriberMethods which calls createSubscriberMethod which looks like:

    protected SubscriberMethod createSubscriberMethod(String methodName, Class<?> eventType, ThreadMode threadMode,
                                                      int priority, boolean sticky) {
        try {
            Method method = subscriberClass.getDeclaredMethod(methodName, eventType);
            return new SubscriberMethod(method, eventType, threadMode, priority, sticky);
        } catch (NoSuchMethodException e) {
            throw new EventBusException("Could not find subscriber method in " + subscriberClass +
                    ". Maybe a missing ProGuard rule?", e);
        }
    }

This throws NoSuchMethodException. However, it doesn't seem to be the NoSuchMethodException that getDeclaredMethod throws. It's thrown because, on devices running API 8 and below, the method getDeclaredMethod does not exist.

This results in a confusing exception message (it's got nothing to do with ProGuard).

Quick fix would be to modify addIndex to be something like

    /** Adds an index generated by EventBus' annotation preprocessor. */
    public EventBusBuilder addIndex(SubscriberInfoIndex index) {
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.FROYO) {
            Log.w(TAG, "Running on API < 9, ignoring generated index");
            return this;
        }
        if(subscriberInfoIndexes == null) {
            subscriberInfoIndexes = new ArrayList<>();
        }
        subscriberInfoIndexes.add(index);
        return this;
    }

and note this in the documentation.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions