Closed rpattabi closed 7 years ago
I ran into a similar issue with no class def found - I've opened an issue in retrolambda itself rather than the gradle plugin: https://github.com/orfjackal/retrolambda/issues/126
No resolution yet, I've ended up switching to use Jack and proper java 8 (although it doesn't support default methods etc), but I'm running into the same problem with a different lambda there now.
From what I've been reading about the issue when it happens with Jack, it might be something to do with multidex - see https://code.google.com/p/android/issues/detail?id=213483
@rpattabi I think you might be getting NoClassDefFoundError because Iterable.forEach takes an instance of Consumer interface which is only available on API 24+. That seems like pretty normal behaviour because Retrolambda does not backport any Java 8 APIs.
@zergtmn In the code I gave above, do you mean Listener
is consumer interface and iterable<Listener>.forEach
is not supported by retrolambda?
If you meant I am using an interface only available on API 24+, that's not the case since Listener
is a user defined interface as shown in the code.
Are you building for nougat only? Otherwise I'd be very surprised if calling Iterable.forEach works considering it's a default method on an interface - and even the new Jack compiler that does support lambdas doesn't support those on marshmallow or earlier. Retrolambda does it for your own classes but not with library methods. So no, foreach is probably not supported by retrolambda.
I'm actually surprised that android studio doesn't warn you about calling forEach...
What he means is that forEach takes an argument (java.util.function.Consumer<? super T> action), and that for anything less than Nougat the class won't exist; hence the NoClassDefFoundError for your anonymous class as it's trying to implement an interface that doesn't exist.
I've raised an issue about a similar issue on the retrolambda project (https://github.com/orfjackal/retrolambda/issues/126), except not for foreach.
If you really want to use foreach you could copy the implementation of Consumer to your own interface class and implement a helper, something like
public interface Consumer<T> {
void accept(T t);
}
public class ArrayUtils {
public static <T> void forEach(Iterable<T> iterable, Consumer<? super T> action) {
for (T t : iterable) {
action.accept(t);
}
}
}
Are you building for nougat only?
No. I have min sdk: 16 and target sdk: 24.
forEach takes an argument (java.util.function.Consumer<? super T> action), and that for anything less than Nougat the class won't exist
I see what you mean. This code compiles which is surprising to me. I guess it is due to latest build tools I am using.
Thanks for the work around. I will close this issue since retrolambda or gradle-retrolambda doesn't have anything to do here.
Problematic code
This works
Instead of
listeners.forEach(listener -> listener.started(exercise));
, if we iterate like below it works even with proguard:Config