Android应用程序窗口View的创建过程.docx
《Android应用程序窗口View的创建过程.docx》由会员分享,可在线阅读,更多相关《Android应用程序窗口View的创建过程.docx(21页珍藏版)》请在冰豆网上搜索。
Android应用程序窗口View的创建过程
Android应用程序窗口View的创建过程
View类是Android中非常重要的一个类.view是应用程序界面的直观体现,我们看到的应用程序界面就可以看作是View(视图)组成的.
那么我们应用程序的界面是怎么创建的呢,也就是应用程序的View是什么时候创建的?
在android中与界面直接相关的就是Activity了.
我们平时在Activity的onCreate()函数中,通过调用它的setContentView()函数,将我们应用程序的界面资源设置进去.然后运行程序就可以看到我们布局文件里描述的界面了.
从我们调用setContentView()函数将界面资源设置进去,到运行完成界面完全显示出来,其中经过了很多过程.
这里我主要是通过源码来分析一下其中最终界面到底是什么样的View?
然后分析一下View的measure,layout,draw过程.
因为我们设置界面是setContentView()中设置的,所以就从该函数开始来分析.
在
分析点击android桌面app图标启动应用程序的过程一文中我们知道Activity的onCreate()函数最先被调用.第五十步
[java]viewplaincopy在CODE上查看代码片派生到我的代码片
privateActivityperformLaunchActivity(ActivityClientRecordr,IntentcustomIntent){
....
Activityactivity=null;
try{
java.lang.ClassLoadercl=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(Exceptione){
....
}
try{
Applicationapp=r.packageInfo.makeApplication(false,mInstrumentation);
...
if(activity!
=null){
ContextappContext=createBaseContextForActivity(r,activity);
CharSequencetitle=r.activityInfo.loadLabel(appContext.getPackageManager());
Configurationconfig=newConfiguration(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;
inttheme=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]viewplaincopy在CODE上查看代码片派生到我的代码片
publicvoidsetContentView(intlayoutResID){
getWindow().setContentView(layoutResID);
initActionBar();
}
publicvoidsetContentView(Viewview){
getWindow().setContentView(view);
initActionBar();
}
publicvoidsetContentView(Viewview,ViewGroup.LayoutParamsparams){
getWindow().setContentView(view,params);
initActionBar();
}
Activity中setContentView()函数有三个重载函数,一般用第一个比较多,这里就按第一个继续往下分析,其实它们最终实现都一样.
首先看getWindow()函数
第二步:
getWindow()
在frameworks/base/core/java/android/app/Activity.java中
[java]viewplaincopy在CODE上查看代码片派生到我的代码片
publicWindowgetWindow(){
returnmWindow;
}
Activity的成员变量mWindow是Window类型,它是什么时候被赋值的呢?
这里还是到分析点击android桌面app图标启动应用程序的过程一文中第五十步看看
[java]viewplaincopy在CODE上查看代码片派生到我的代码片
privateActivityperformLaunchActivity(ActivityClientRecordr,IntentcustomIntent){
....
Activityactivity=null;
try{
java.lang.ClassLoadercl=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(Exceptione){
...
}
try{
Applicationapp=r.packageInfo.makeApplication(false,mInstrumentation);
...
if(activity!
=null){
ContextappContext=createBaseContextForActivity(r,activity);
CharSequencetitle=r.activityInfo.loadLabel(appContext.getPackageManager());
Configurationconfig=newConfiguration(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]viewplaincopy在CODE上查看代码片派生到我的代码片
finalvoidattach(Contextcontext,ActivityThreadaThread,
Instrumentationinstr,IBindertoken,intident,
Applicationapplication,Intentintent,ActivityInfoinfo,
CharSequencetitle,Activityparent,Stringid,
NonConfigurationInstanceslastNonConfigurationInstances,
Configurationconfig){
...
mWindow=PolicyManager.makeNewWindow(this);//
....
}
mWindow=PolicyManager.makeNewWindow(this);这里就是给activity中mWindow赋值.那继续看PolicyManager.makeNewWindow(this)这个函数
第四步:
makeNewWindow()
在frameworks/base/core/Java/com/android/internal/policyPolicyManager.java中
[java]viewplaincopy在CODE上查看代码片派生到我的代码片
//Thestaticmethodstospawnnewpolicy-specificobjects
publicstaticWindowmakeNewWindow(Contextcontext){
returnsPolicy.makeNewWindow(context);
}
[java]viewplaincopy在CODE上查看代码片派生到我的代码片
[java]viewplaincopy在CODE上查看代码片派生到我的代码片
publicfinalclassPolicyManager{
privatestaticfinalStringPOLICY_IMPL_CLASS_NAME=
"com.android.internal.policy.impl.Policy";
privatestaticfinalIPolicysPolicy;
static{
//Pullintheactualimplementationofthepolicyatrun-time
try{
ClasspolicyClass=Class.forName(POLICY_IMPL_CLASS_NAME);
sPolicy=(IPolicy)policyClass.newInstance();
}catch(ClassNotFoundExceptionex){
....
}
这里继续调用sPolicy.makeNewWindow(context);由上面代码可以知道这里的sPolicy其实是Policy类型
第五步:
makeNewWindow()
在frameworks/base/policy/src/com/android/internal/policy/impl/Policy.java中
[java]viewplaincopy在CODE上查看代码片派生到我的代码片
publicclassPolicyimplementsIPolicy{
.
publicWindowmakeNewWindow(Contextcontext){
returnnewPhoneWindow(context);
}
这里直接newPhoneWindow(context)返回,可知PhoneWindow类是Window类的子类,进入PhoneWindow类看看
第六步:
PhoneWindow()
在frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java中
[java]viewplaincopy在CODE上查看代码片派生到我的代码片
publicclassPhoneWindowextendsWindowimplementsMenuBuilder.Callback{
.
publicPhoneWindow(Contextcontext){
super(context);
mLayoutInflater=LayoutInflater.from(context);
}
来看一下PhoneWindow类的构造函数,首先是调用了其父类(Window)的构造函数,然后创建了一个LayoutInflater对象mLayoutInflater,这个对象根据它的名字大概可以知道它是渲染布局资源的
去Window类的构造函数看看
第七步:
Window()
在frameworks/base/core/java/android/view/Window.java中
[java]viewplaincopy在CODE上查看代码片派生到我的代码片
publicWindow(Contextcontext){
mContext=context;
}
回到第二步中,这是我们知道getWindow()返回其实是一个PhoneWindow对象,即Activity的成员变量mWindow是PhoneWindow类型.
然后回到第一步中,那么接着其实是调用PhoneWindow.setContentView()了
第八步:
setContentView()
在frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java中
[java]viewplaincopy在CODE上查看代码片派生到我的代码片
publicvoidsetContentView(intlayoutResID){
if(mContentParent==null){
installDecor();
}else{
mContentParent.removeAllViews();
}
mLayoutInflater.inflate(layoutResID,mContentParent);
finalCallbackcb=getCallback();
if(cb!
=null&&!
isDestroyed()){
cb.onContentChanged();
}
}
PhoneWindow的成员变量mContentParent是ViewGroup类型,第一次进来为null,所以调用installDecor()函数,那我们首先看看该函数
第九步:
installDecor()
在frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java中
[java]viewplaincopy在CODE上查看代码片派生到我的代码片
privatevoidinstallDecor(){
if(mDecor==null){
mDecor=generateDecor();
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
...
}
if(mContentParent==null){
mContentParent=generateLayout(mDecor);
//SetupdecorpartofUItoignorefitsSystemWindowsifappropriate.
mDecor.makeOptionalFitsSystemWindows();
mTitleView=(TextView)findViewById(com.android.internal.R.id.title);
if(mTitleView!
=null){
mTitleView.setLayoutDirection(mDecor.getLayoutDirection());
if((getLocalFeatures()&(1<=0){
ViewtitleContainer=findViewById(com.android.internal.R.id.title_container);
if(titleContainer!
=null){
titleContainer.setVisibility(View.GONE);
}else{
mTitleView.setVisibility(View.GONE);
}
if(mContentParentinstanceofFrameLayout){
((FrameLayout)mContentParent).setForeground(null);
}
}else{
mTitleView.setText(mTitle);
}
}else{
mActionBar=(ActionBarView)findViewById(com.android.internal.R.id.action_bar);
if(mActionBar!
=null){
mActionBar.setWindowCallback(getCallback());
if(mActionBar.getTitle()==null){
mActionBar.setWindowTitle(mTitle);
}
finalintlocalFeatures=getLocalFeatures();
if((localFeatures&(1<=0){
mActionBar.initProgress();
}
if((localFeatures&(1<=0){
mActionBar.initIndeterminateProgress();
}
booleansplitActionBar=false;
finalbooleansplitWhenNarrow=
(mUiOptions&ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW)!
=0;
if(splitWhenNarrow){
splitActionBar=getContext().getResources().getBoolean(
com.android.internal.R.bool.split_action_bar_is_narrow);
}else{
splitActionBar=getWindowStyle().getBoolean(
com.android.internal.R.styleable.Window_windowSplitActionBar,false);
}
finalActionBarContainersplitView=(ActionBarContainer)findViewById(
com.android.internal.R.id.split_action_bar);
if(splitView!
=null){
mActionBar.setSplitView(splitView);
mActionBar.setSplitActionBar(splitActionBar);
mActionBar.setSplitWhenNarrow(splitWhenNarrow);
finalActionBarContextViewcab=(ActionBarContextView)findViewById(
com.android.internal.R.id.action_context_bar);
cab.setSplitView(splitView);
cab.setSplitActionBar(splitActionBar);
cab.setSplitWhenNarrow(splitWhenNarrow);
}elseif(splitAionBar){
Log.e(TAG,"Requestedsplitact