A better custom ViewGroup

Barend Garvelink

Jerome P. commented on my earlier post denouncing the ViewHolder pattern. He suggested an improvement to the ViewGroup approach that inverts the direction of dependency between the ContactView and its layout XML file. Instead of referencing the custom class from XML, the Java code now references the layout file using a standard resource reference. This adds further type safety and it means your view class can be completely ProGuarded.

The list adapter implementation becomes more convenient. It no longer needs to use a layout inflater, it can simply new up an instance of the view class:

    public View getView(int position, View convertView, ViewGroup parent) {
        ContactView view;
        if (convertView == null) {
            view = new ContactView(context);
            // Was: view = (ContactView) inflater.inflate(R.layout.list_item, null);
        }
        // continued...
    }

To do this, change the root element of the XML layout to <merge/> and modify the constructors of the custom view group:

public class ContactView extends LinearLayout {

    // private field declarations

    /** Inherited constructor. */
    public ContactView(Context context) {
        super(context);
        init(context);
    }

    /** All three constructors invoke this method. */
    private void init(Context context) {
        setOrientation(VERTICAL);
        LayoutInflater.from(context).inflate(R.layout.contact_view, this, true);
        nameView = (TextView) findViewById(R.id.contact_name);
        emailView = (TextView) findViewById(R.id.contact_email);
        addressView = (TextView) findViewById(R.id.contact_address);
    }

    // continued

The complete code for this example has been added to the 4-_better_custom_ViewGroup branch of the android-cciaa repository on GitHub.

Comments (8)

  1. Andhie - Reply

    August 5, 2013 at 3:20 am

    using the <merge/> tag is all good if it was a simple LinearLayout. what about views that uses RelativeLayout? i could only think of 2 approach.
    1. use <merge><RelativeLayout>. this would introduce a useless parent container after merging/inflate
    2. pretend <merge> is a RelativeLayout, i.e. continue using Layout specific attributes on the child view and in the View java class, extends RelativeLayout.

    what would your approach be?

  2. Chris - Reply

    October 14, 2013 at 2:50 pm

    This sounds good, but I guess there's a downside to instantiating the custom view yourself, in that it won't inherit your theme properties.

  3. Lester Bambico - Reply

    January 9, 2014 at 2:19 pm

    Hi, I came across your post accidentally looking for animation alternatives to ViewAnimator.

    Although completely unrelated, I was guilty of using the classic adapter approach and have been suffering performance issues when handling large lists.
    I tried implementing your 'better custom viewgroup' but stumbled upon a roadblock.

    How do you implement this with listeners for lists such as a to-do-list for example where we have a linear layout with an edit text and checkboxes?

  4. James HO - Reply

    October 10, 2014 at 11:41 am

    Last sentence in your first paragraph:
    "This adds further type safety and it means your view class can be completely ProGuarded."
    May I ask what it means? I don't get it.

Add a Comment