Android应用程序窗口View的创建过程 下载本文

内容发布更新时间 : 2024/6/22 19:01:22星期一 下面是文章的全部内容请认真阅读。

Android应用程序窗口View的创建过程

View类是Android中非常重要的一个类.view是应用程序界面的直观体现,我们看到的应用程序界面就可以看作是View(视图)组成的.

那么我们应用程序的界面是怎么创建的呢,也就是应用程序的View是什么时候创建的?

在android中与界面直接相关的就是Activity了.

我们平时在Activity的onCreate()函数中,通过调用它的setContentView()函数,将我们应用程序的界面资源设置进去.然后运行程序就可以看到我们布局文件里描述的界面了.

从我们调用setContentView()函数将界面资源设置进去,到运行完成界面完全显示出来,其中经过了很多过程.

这里我主要是通过源码来分析一下其中最终界面到底是什么样的View? 然后分析一下View的measure,layout,draw过程.

因为我们设置界面是setContentView()中设置的,所以就从该函数开始来分析. 在

分析点击android桌面app图标启动应用程序的过程一文中我们知道Activity的onCreate()函数最先被调用.第五十步 [java] view plain copy 在CODE上查看代码片派生到我的代码片

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ....

Activity activity = null; try {

java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent);

StrictMode.incrementExpectedActivityCount(activity.getClass()); r.intent.setExtrasClassLoader(cl); if (r.state != null) {

r.state.setClassLoader(cl); }

} catch (Exception e) { .... }

try {

Application app = r.packageInfo.makeApplication(false, mInstrumentation); ...

if (activity != null) {

Context appContext = createBaseContextForActivity(r, activity);

CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); Configuration config = new Configuration(mCompatConfiguration); ...

activity.attach(appContext, this, getInstrumentation(), r.token,

r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config);

if (customIntent != null) {

activity.mIntent = customIntent; }

r.lastNonConfigurationInstances = null; activity.mStartedActivity = false;

int theme = r.activityInfo.getThemeResource(); if (theme != 0) {

activity.setTheme(theme); }

activity.mCalled = false;

mInstrumentation.callActivityOnCreate(activity, r.state); ..... }

这里首先创建Activity 的实例,然后mInstrumentation.callActivityOnCreate(activity, r.state)该函数最终就会调用Activity的onCreate()函数. 好了,看setContentView()函数 第一步:setContentView()

在frameworks/base/core/java/android/app/Activity.java中 [java] view plain copy 在CODE上查看代码片派生到我的代码片 public void setContentView(int layoutResID) { getWindow().setContentView(layoutResID); initActionBar(); }

public void setContentView(View view) { getWindow().setContentView(view); initActionBar(); }

public void setContentView(View view, ViewGroup.LayoutParams params) { getWindow().setContentView(view, params); initActionBar(); }

Activity中setContentView()函数有三个重载函数,一般用第一个比较多,这里就按第一个继续往下分析,其实它们最终实现都一样. 首先看getWindow()函数 第二步:getWindow()

在frameworks/base/core/java/android/app/Activity.java中 [java] view plain copy 在CODE上查看代码片派生到我的代码片 public Window getWindow() { return mWindow; }

Activity的成员变量mWindow是Window类型,它是什么时候被赋值的呢?

这里还是到分析点击android桌面app图标启动应用程序的过程一文中第五十步 看看

[java] view plain copy 在CODE上查看代码片派生到我的代码片

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ....

Activity activity = null; try {

java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent);

StrictMode.incrementExpectedActivityCount(activity.getClass()); r.intent.setExtrasClassLoader(cl); if (r.state != null) {

r.state.setClassLoader(cl); }

} catch (Exception e) { ... }

try {

Application app = r.packageInfo.makeApplication(false, mInstrumentation); ...

if (activity != null) {

Context appContext = createBaseContextForActivity(r, activity);

CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); Configuration config = new Configuration(mCompatConfiguration); ...

activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config);

.... }

这里创建Activity的实例后,就通过activity.attach()函数给activity内部变量赋值,所以进attach()函数里面看看 第三步:attach()

在frameworks/base/core/java/android/app/Activity.java中

[java] view plain copy 在CODE上查看代码片派生到我的代码片 final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id,

NonConfigurationInstances lastNonConfigurationInstances, Configuration config) { ...

mWindow = PolicyManager.makeNewWindow(this);// ....