Cleaner View Casting with Generics

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

If you've written anything in Android, I'm sure you've written something similar to this line numerous times. I know I have, and while writing some code today, I came up with a useful method which removes the need for the cast. It's very trivial, and probably common knowledge, but I'd just never thought to apply it for this case until now.

So I've added the following method to my base Activity class (which all Activities in the project extend) which uses generics to infer the type of View it should be cast to:

@SuppressWarnings("unchecked")
public final <E extends View> E findView (int id) {
    return (E) findViewById(id);
}

(ed: Previously, this did a try/catch but simply logged the result. Removed it since it was unnecessary)

So now, you can simply say:

TextView textView = findView(R.id.textview);
Button button = findView(R.id.button);
ImageView image = findView(R.id.imageview);

Obviously you still have to make sure that the ID matches a View in your layout hierarchy which is the correct type, but this simply eliminates some of the boilerplate code. One limitation is that you still have to cast if you wanted to inline that call to a method that required an instance of a specific View type. For example:

private static void myMethod (ImageView img) {
    //Do nothing
}

@Override
public void onCreate (Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    myMethod(findView(R.id.imageview)); //Will not compile

    myMethod((ImageView) findView(R.id.imageview)); //Compiles
}

NOTE: As +Gavin King brought up in the comments, it seems worth noting that this is not a typical use case for generics, and does not bring any of the type safety guarantees that generics should be used for. This is an example that is very specific to this usage in the Android framework, as unchecked casting is the norm for acquiring View references in Android. This simply moves the cast into your base Activity's code.


public <T> T findById(int id) { return (T) findViewById(id); }

你可能感兴趣的:(android,generics,findViewById)