Question

As I'm tired of writing a cast operator for EVERY Activity.findViewById() that returns raw View, I finally tried one way that was suggested by Internet.

public abstract class MyActivity extends Activity {

    @SuppressWarnings("unchecked")
    protected <T extends View> T findViewByID(int id) {
        return (T) this.findViewById(id);
    }
}

Note this isn't overloaded (the last "D" is upper case). The compiler says we can't cast View into T. Is there anything wrong with my implementing? Strangely, this suggestion was hardly seen in English websites (e.g. even in our lovely Stack Overflow), and the exception was the site posted above.

Was it helpful?

Solution

This works fine in my test project. No compiler error: screenshot

OTHER TIPS

To be honest, this approach adds some subtle complexity overhead for the next Android maintainer (who would be used to the casting approach) to save a few characters in the code files.

I would propose to cast the Views in the traditional way, or opt for a reflection-based solution like Roboguice.

I solved this by using a custom eclipse-builder that generates classes with references for each layout-file, because:

  • It's typesafe and easy to use
  • RoboGuice and all other reflection-based APIs are very slow on Android.

In my opinion this is the cleanest and most performant way of solving this problem.

See my gist here for the builder: https://gist.github.com/fab1an/10533872

Layout: test.xml

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" >

    <TextView
        android:id="@+id/text1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/text2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/text1" />

    <ScrollView
        android:id="@+id/scroll"
        android:layout_width="match_parent"
        android:layout_height="350px"
        android:layout_below="@id/text2"
        android:layout_marginTop="50px" />

</merge>

usage: TestView.java

public final class TestView extends RelativeLayout {

    //~ Constructors ---------------------------------------------------------------------------------------------------
    private final ViewRef_test v;

    public TestView(final Context context) {
        super(context);

        LayoutInflater.from(context).inflate(R.layout.test, this, true);
        this.v = ViewRef_test.create(this);

        this.v.text1.setText();
        this.v.scroll.doSomething();
    }
}

generated file (in gen/): ViewRef_test.java

package org.somecompany.somepackage;

import android.view.*;
import android.widget.*;
import java.lang.String;


@SuppressWarnings("unused")
public final class ViewRef_test {

    public final TextView text1;
    public final TextView text2;
    public final ScrollView scroll;


    private ViewRef_test(View root) {
        this.text1 = (TextView) root.findViewById(R.id.text1);
        this.text2 = (TextView) root.findViewById(R.id.text2);
        this.scroll = (ScrollView) root.findViewById(R.id.scroll);
    }

    public static ViewRef_test create(View root) {
        return new ViewRef_test(root);
    }


}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top