David David - 5 months ago 27
Android Question

Determine required object type from uninitialized object

I would like my code to help determine what object type is required automatically.

Background:

The code to attach a widget is often as follows:

TextView textView = (TextView) findViewById(R.id.textView);


I want to then check that textView has been found correctly in order to avoid bugs. To do this, I'm using a custom (AttachWidgetException) exception:

if(textView == null) throw new AttachWidgetException(name);


Idea:

Rather than having to repeat these two lines for every widget in my code (DRY), I decided to make a function to simplify it. I incorrectly assumed I could do this:

public View attachWidget(View view, int resID, String name) throws AttachWidgetException {
view = (view.getClass) findViewById(resID);

if(view == null) throw new AttachWidgetException(name);
return view;
}


Called from within a Try block by:

TextView textView = attachWidget(textView, R.id.textView, "textView");


Problem:

But, this doesn't work for two reasons. The caller's object is expecting a TextView not a View. I think the other reason is view is yet to be instantiated and therefore is reported as:

java.lang.Class <capture<? extends android.view.View>


… which is not an extension of View. To fix this, I need to change the line in attachWidget to:

view = findViewById(resID);


...and the calling line to:

TextView textView = (TextView) attachWidget(textView, R.id.textView, "textView");


… which makes the View input parameter useless. We can remove that at this point.

Question:

This really isn't too bad, but is there a way to do this so I don't need to manually add the cast? Can attachWidget automatically determine that it needs to return a TextView? I'm pretty sure I'm heading in the wrong direction of any possible solutions. Would generics help me in any way here?

Please forgive me if I am using incorrect terminology in my description. I would appreciate any code / terminology / methodology corrections.

Answer

You can't call view.getClass when view is null. Try doing this:

public <T extends View> T attachWidget(Class<T> type, int resID, String name) throws AttachWidgetException {
        View view = findViewById(resID);
        if (view == null) throw new AttachWidgetException(name);
    try {
        return type.cast(view);  
    } catch (ClassCastException) {
        e.printStackTrace();
        throw new AttachWidgetException(name);
    } 
}

In this case, you can call like:

TextView textView = attachWidget(TextView.class, R.id.textView, "textView");
Comments