Android: setContentView() == getViewInflate().infl

2020-06-23 05:59发布

问题:

I try my hardest to develop a clever way to clean out piles of Blah blah = (Blah) this.findViewById(R.id.blah) that otherwise pollute the field and the onCreate() method of my little Activity, and to do so, I feel I should not use setContentView() but getViewInflate().inflate() for every View defined in XMLs.

Is Activity.setContentView() is sorta a syntax sugar and it's virtually repeating getViewInflate().inflate() for every View on XML? I read something saying as if they were the same.

If I can get an answer by looking into the code, please tell so. I checked Activity.class, but only comments were found.

回答1:

The setContentView on your Activity actually calls the setContentView on the Window used by the activity, which itself does a lot more than just inflating the layout.

What you could do is to map the views to the class field using reflexion. You can download a utility class on Github that does this.

It will parse all the views declared in the layout, then try to find the name corresponding to the id in your R.id class. Then it will try to find a field with the same name in the target object and set it with the corresponding view.

For example, if you have a layout like this

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

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

it will automatically map it to a textView1 field in your activity.



回答2:

I'm posting my poor research. In summary, Activity.setContentView() delegates PhoneWindow.setContentView() (the only concrete class of Window ) within which LayoutInflater.inflate() is called, so saying "setContentView() == ViewInflate().inflate()" is not so overly off, I guess.

public class Activity extends {

    private Window mWindow;

    public void setContentView(int layoutResID) {
        getWindow().setContentView(layoutResID);
        initActionBar();
    }

    public Window getWindow() {
        return mWindow;
    }
}



public class PhoneWindow extends Window {

    private LayoutInflater mLayoutInflater;

    @Override
    public void setContentView(int layoutResID) {
        if (mContentParent == null) {
            installDecor();
        } else {
            mContentParent.removeAllViews();
        }
        **mLayoutInflater.inflate(layoutResID, mContentParent);**
        final Callback cb = getCallback();
        if (cb != null) {
            cb.onContentChanged();
        }
    }
}


回答3:

Actually you're right, there's two ways to achieve the same thing:

1) setContentView(R.layout.layout);

2)

LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
View v = inflater.inflate(R.layout.layout, null);
setContentView(v);

You decide what is more appropriate for you. Hope this helps.