My outer problem, in Java 1.8, is I want to traverse (or spider) a tree of View objects and call a callback on each one of a specific type. Here's an example caller:
findEachView(main.popupForm, (EditText v) -> {
CharSequence error = v.getError();
if (error != null)
assertNull((String) v.getTag(), error.toString());
});
That is supposed to traverse all the controls on the popupForm and, for each one that is an EditText, call my callback which asserts that it does not have an error.
The inner problem is my generic method to do it has a syntax error:
static <T extends View> void findEachView(@NonNull ViewGroup view, @NonNull Consumer<T> viewAdjustorVisitor) {
for (int i = 0; i < view.getChildCount(); i++) {
View v = view.getChildAt(i);
if (v instanceof T) // ERROR: reifiable types in instanceof are not supported in -source 8
viewAdjustorVisitor.accept((T) v);
if (v instanceof ViewGroup)
findEachView((ViewGroup) v, viewAdjustorVisitor);
}
}
So my outer question is: How to efficiently and typesafely rip every View of the given type?
And my inner question is: How to get the generics to not throw away type information and let me call instanceof
on a type that I know is reified?
We can't use isAssignableFrom()
because it takes an object of type T
and my template doesn't have one. Its point is to downcast a View
into a T
, not mess with a T
object that already exists. And I can't create a new
object because T
is "not reified":
if (v.getClass().isAssignableFrom(new T()))
So maybe if someone could answer the outer question instead of downvoting?
when I add the ?
we get this, with the next syntax error. I think this is an unanswered question in Java 1.8 template theory
static <T extends View> void findEachView(@NonNull
ViewGroup viewGroup, @NonNull
Consumer<Class<? extends View>> visitor) {
for (int i = 0; i < viewGroup.getChildCount(); i++) {
View v = viewGroup.getChildAt(i);
if (null != (Class <? extends android.view.View>) v) // ERROR: incompatible types: View cannot be converted to Class<? extends View>
visitor.accept((Class <? extends android.view.View>) v);
if (v instanceof ViewGroup)
findEachView((ViewGroup) v, visitor);
}
}