10

I just wrote an answer for someone confused by findViewById and I realised that I have a gap in my understanding. This question is for knowledge and curiosity only.

Consider this:

button = (Button)findViewById(R.id.button);

findViewById returns an instance of View, which is then cast to the target class. All good so far.

To setup the view, findViewById constructs an AttributeSet from the parameters in the associated XML declaration which it passes to the constructor of View.

We then cast the View instance to Button.

How does the AttributeSet get passed in turn to the Button constructor?

[EDIT]

So I was the confused one :). The whole point is that when the layout is inflated, the view hierarchy already contains an instance of the view descendant class. findViewById simply returns a reference to it. Obvious when you think about it - doh..

Simon
  • 14,407
  • 8
  • 46
  • 61
  • +5 for the queston....because of your question I have researched and find the complete information regarding the basic flow....thanks to @Leonidos – Pragnani Feb 10 '13 at 19:07

2 Answers2

14

findViewById does nothing. It just looks through view hierarchy and returns reference to a view with requested viewId. View is already created and exists. If you do not call findViewById for some view nothing changes.

Views are inflated by LayoutInflator. When you call setContentView xml layout is parsed and view hierarchy is created.

attributes passed to Button's constructor by LayoutInflater. check LayoutInflator source code.

Mithun
  • 2,075
  • 3
  • 19
  • 26
Leonidos
  • 10,482
  • 2
  • 28
  • 37
  • Ah, I get it. You mean in the view heirarchy, the referenced view is already instantiated by calling the ctor of the correct descendant class? – Simon Feb 10 '13 at 18:30
  • attributes passed to Button's constructor by layout inflater. check [LayoutInflarot source code](http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/view/LayoutInflater.java#LayoutInflater.inflate%28org.xmlpull.v1.XmlPullParser%2Candroid.view.ViewGroup%2Cboolean%29). – Leonidos Feb 10 '13 at 18:35
6

I don't think findViewById() constructs or instantiates a View. It will search in View hierarchy of already inflated layout, for a View with matching id.This method works differently for a View and for a ViewGroup.

from Android Source code:

View.findViewById() returns the same View object if this view has the given id or null, it calls:

protected View findViewTraversal(int id) {
    if (id == mID) {
        return this;
    }
    return null;
}

ViewGroup.findViewById() iterates through child views and calls same method on these Views, it calls:

 protected View findViewTraversal(int id) {
    if (id == mID) {
        return this;
    }

    final View[] where = mChildren;
    final int len = mChildrenCount;

    for (int i = 0; i < len; i++) {
        View v = where[i];

        if ((v.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
            v = v.findViewById(id);

            if (v != null) {
                return v;
            }
        }
    }

    return null;
}
S.D.
  • 29,290
  • 3
  • 79
  • 130
  • what is mId, when I search in the view class mId is assigned to No_ID..where did it assign mId to the traversed View id – Pragnani Feb 10 '13 at 18:58
  • @Pragnani `mId` is view's assigned ID. when you/inflater call `setId(int id)` on a view, `mID` is set to supplied int value. – S.D. Feb 10 '13 at 19:01