您的位置:首页 > 移动开发 > Android开发

Android源码如何给Activity渲染布局

2017-09-22 16:35 183 查看
    相信做Android应用的一些程序猿,虽然做了几个项目,但是可能还不知道我们Android系统如何给Activity渲染布局的,今天我不要脸地简单介绍一下,也算自己学习记录一下。

我们都知道,我们自己创建了XXActivity会去继承系统的Activity类,也知道Activity是通过setContentView()这个方法把布局渲染进去的。在Activity类中,我们可以找到这个方法:

public void setContentView(@LayoutRes int layoutResID) {

        getWindow().setContentView(layoutResID);

        initWindowDecorActionBar();

    }

从这个方法分析,getWindow()是返回一个Window对象,我们找到Window类,在这个类中我们可以发现这个抽象方法:
public abstract void setContentView(@LayoutRes int layoutResID);
从而我们可以知道一定有一个类去继承Window这个抽象类并实现setContentView()这个方法,那么究竟是哪个类去继承它呢?上面说到在Activity类中获取Window对象可以直接调用getWindow(),从而推知在Activity类中必然也会有去创建Window这个实现类,通过查找可发现:

mWindow = new PhoneWindow(this, window);

这个时候我们就知道PhoneWindow必是Window的实现类,那么再来查找PhoneWindow这个类,通过全局查找并未找到这个类,那这个类究竟放在哪里呢?这个时候我们想到去sdk里面查找,果不其然,可以找到这个类。那么我们在PhoneWindow这个类中再去找setContentView()

这个方法的实现,如下:

    @Override

    public void setContentView(int layoutResID) {

        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window

        // decor, when theme attributes and the like are crystalized. Do not check the feature

        // before this happens.

        if (mContentParent == null) {

            installDecor();

        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {

            mContentParent.removeAllViews();

        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {

            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,

                    getContext());

            transitionTo(newScene);

        } else {

            mLayoutInflater.inflate(layoutResID, mContentParent);

        }

        mContentParent.requestApplyInsets();

        final Callback cb = getCallback();

        if (cb != null && !isDestroyed()) {

            cb.onContentChanged();

        }

        mContentParentExplicitlySet = true;

    }

打开mLayoutInflater.inflate(layoutResID, mContentParent)这句代码关联,跳到LayoutInflater类中:
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {

        return inflate(resource, root, root != null);

    }
再点开inflate(resource, root, root != null),跳到下面这个方法中:
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {

         final Resources res = getContext().getResources();

        if (DEBUG) {

            Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("

                    + Integer.toHexString(resource) + ")");

        }

        final XmlResourceParser parser = res.getLayout(resource);

        try {

            return inflate(parser, root, attachToRoot);

        } finally {

            parser.close();

        }

    }
在这个方法中我们可以发现final XmlResourceParser parser = res.getLayout(resource);这是xml资源文件的解析器,然后再点开return inflate(parser, root, attachToRoot),如下:
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {......}

最终是调用这个方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息