Android应用程序窗口View的创建过程.docx
- 文档编号:27119022
- 上传时间:2023-06-27
- 格式:DOCX
- 页数:21
- 大小:21.70KB
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
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android 应用程序 窗口 View 创建 过程