2

My application has several activities, and lists of "start activity" buttons. I created a custom view for this. So that I don't need to deal with click handlers and switch statements, I can set a custom:start_activity=".OtherActivity" attribute in the layout's XML file.

Sure, nice plan. But I have to provide error detection for that. The typed string in start_activity must be a valid class name, and the class must be child of Activity. OtherActivity is a subclass of a class that is a subclass of AppCompatActivity.

This is what I've tried:

String name = array.getString(R.styleable.MyView_start_activity);
if (name == null)
    throw new IllegalArgumentException("name attribute must be set.");
final String className = context.getPackageName() + activity;
try {
    Class<?> check = Class.forName(className); //, false, getClass().getClassLoader()); // create only at click later
    if (!Activity.class.isInstance(check))
        throw new IllegalArgumentException(className + " is not a valid activity.");
} catch (ClassNotFoundException e) {
    throw new IllegalArgumentException(className + " is not a valid class.");
}

However, that isInstance always returns false, so it throws the exception all the time. I've also tried isAssignableFrom, and different argument/class variants. The given string is a valid class, ClassNotFoundException isn't thrown, and in the debugger, I can see Activity in check's superclass tree. I have no idea, what am I doing wrong?

Vin Norman
  • 2,749
  • 1
  • 22
  • 33
klenium
  • 2,468
  • 2
  • 24
  • 47
  • 3
    `ClassA instanceof ClassB` – Martin Pfeffer Oct 28 '17 at 13:51
  • would using if (check instanceof Activity) work? – Vin Norman Oct 28 '17 at 13:51
  • 1
    Nope. `instanceof` does a static check, so I can't use it. `Class>` cannot be casted in compile time. – klenium Oct 28 '17 at 14:16
  • I think check - or Class.forName(className), is never instantiated. You could try check.newInstance()? – Vin Norman Oct 28 '17 at 14:17
  • @VinNorman Idneed. I was following [this](https://stackoverflow.com/questions/5754855/how-can-i-start-a-new-android-activity-using-a-string) answer, and it didn't include `newInstance()`. Now it looks fine, thanks. Post it as an answer and I'll accept. – klenium Oct 28 '17 at 14:25
  • Note for others: this is not needed at all. See [this answer/comment](https://stackoverflow.com/questions/5754855/how-can-i-start-a-new-android-activity-using-a-string#comment79398953_10904471). Goddamn... – klenium Oct 28 '17 at 14:53

1 Answers1

1

isInstance() and the instanceOf won't work unless the check is instantiated/is an object.

You could do

if (!Activity.class.isInstance(check.newInstance()))

or

if (!(check.newInstance() instanceof Activity))

Assuming it is safe to instantiate your object for this check.

Vin Norman
  • 2,749
  • 1
  • 22
  • 33