Android GUI系统-ViewTree的创建(二)
来源:互联网 发布:地面站软件下载 编辑:程序博客网 时间:2024/05/19 16:06
View树的创建过程
当AMS通知应用进程来启动一个Activity任务时,最终这个请求会转化为ActivityThread中的一个消息LAUNCH_ACTIVITY,同类型的消息还是RESUME_ACTIVITY,PAUSE_ACTIVITY等。主线程ActivityThread对这个LAUNCH_ACTIVITY消息的处理是整个ViewTree建立的起点。
private class H extends Handler @ActivityThread.java{public void handleMessage(Message msg) {switch (msg.what) {case LAUNCH_ACTIVITY: {//获取scheduleLaunchActivity传递的参数。final ActivityClientRecord r = (ActivityClientRecord) msg.obj;handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");break;}}}}
重点关注其中的performLaunchActivity,handleResumeActivity两个调用。
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) @ActivityThread.java{//如果正准备GC,就先跳过。UnscheduleGcIdler();//在创建Activity之前,初始化。WindowManagerGlobal.initialize();//启动、加载Activity。Activity a = performLaunchActivity(r, customIntent);//resume这个Activity。if (a != null) {handleResumeActivity(r.token, false, r.isForward,!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);}else{//不管什么原因出现的错误,都只能结束Activity的启动,返回给调用者的code是 RESULT_CANCELED。ActivityManagerNative.getDefault().finishActivity(r.token, Activity.RESULT_CANCELED, null,Activity.DONT_FINISH_TASK_WITH_ACTIVITY);}}
1)先分析performLaunchActivity。
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) @ActivityThread.java{ActivityInfo aInfo = r.activityInfo;//如果intent没有明确给出component,将调用 resolveActivity解析出activity component。ComponentName component = r.intent.getComponent();if (component == null) {component = r.intent.resolveActivity(mInitialApplication.getPackageManager());r.intent.setComponent(component);}Activity activity = null;//取得类加载器,加载这个Activity。java.lang.ClassLoader cl = r.packageInfo.getClassLoader();activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);//同样借助类加载器,创建Application对象。Application app = r.packageInfo.makeApplication(false, mInstrumentation);Context appContext = createBaseContextForActivity(r, activity);//attach函数的主要任务是生成PhoneWindow对象,也就是Activity中的mWindow,mWindow分Activity是一对一的关系;还有就是给Activity中的一些变量赋值,如UI线程,main线程等。activity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,r.referrer, r.voiceInteractor, window);//通过Instrumentation工具,间接调用Activity的OnCreate函数。mInstrumentation.callActivityOnCreate(activity, r.state);//把ActivityClientRecord添加到一个arraymap中,其中token是IApplicationToken类型的实例。mActivities.put(r.token, r);}
前面生成的PhoneWindow对象可以看做界面的框架抽象,还要生成Activity要显示的内容,以及应用程序共同的装饰部分,如title,actionbar等。这个填充的过程是从setContentView调用开始的,这也是每个Activity的onCreate方法中都会重写这个函数的原因。
//从layout资源,设置Activity的内容。
public void setContentView(@LayoutRes int layoutResID) {//调用PhoneWindow的 setContentView方法。getWindow().setContentView(layoutResID);//创建一个ActionBar。initWindowDecorActionBar();}
public void setContentView(int layoutResID)@PhoneWindow.java {//mContentParent用于容纳contentView,当其为null时,说明是第一次调用 setContentView,所以调用 installDecor创建一个DecorView,否则就清楚已有的view对象, FEATURE_CONTENT_TRANSITIONS这个flag默认没有设置。if (mContentParent == null) {installDecor();}else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {mContentParent.removeAllViews();}//根据resourceID创建view对象。mLayoutInflater.inflate(layoutResID, mContentParent);}
//mContentParent为null,通过installDecor生成Decorview和mContentParent。private void installDecor()@PhoneWindow.java {if (mDecor == null) {// generateDecor只是创建了一个DecorView对象,赋值给了mDecor。mDecor = generateDecor(-1);}else{mDecor.setWindow(this)}// mContentParent是通过 generateLayout产生的。if (mContentParent == null) {mContentParent = generateLayout(mDecor);}}
protected ViewGroup generateLayout(DecorView decor) @PhoneWindow.java{//获取窗口样式。TypedArray a = getWindowStyle();mIsFloating = a.getBoolean(R.styleable.Window_windowIsFloating, false);//根据窗口样式,请求窗口属性。if (a.getBoolean(R.styleable.Window_windowNoTitle, false)) {requestFeature(FEATURE_NO_TITLE);}else if (a.getBoolean(R.styleable.Window_windowActionBar, false)) {requestFeature(FEATURE_ACTION_BAR);}//根据窗口样式,设置窗口的flags。if (a.getBoolean(R.styleable.Window_windowFullscreen, false)) {setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN & (~getForcedWindowFlags()));}//窗口是不是透明的。mIsTranslucent = a.getBoolean(R.styleable.Window_windowIsTranslucent, false);//得到这个窗口已经实现的feature,前面的requestFeature的结果会保存到mLocalFeatures(getLocalFeatures())中。int layoutResource;int features = getLocalFeatures();//根据前面设置的feature,挑选匹配的资源 layoutResource。if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {}else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {}else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {layoutResource = R.layout.screen_custom_title;}//把 layoutResource资源inflate成view对象,然后把这个view对象addView到mDecor中。mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);//获取主layout:com.android.internal.R.id.content,也是返回值 mContentParent,这个mContentParent的内容实际有setContentView的资源id来填充。ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);return contentParent;}
到这里就生成了phoneWindow,和decorView,DecorView除了包括窗口的装饰条(title,ActionBar等)外,还包括窗口的内容即mContentParent。
2)接着分析:handleResumeActivity。
performLaunchActivity过程中生成的ViewTree,要添加到WindowManagerGlobal中,进一步注册到WMS中。
final void handleResumeActivity(IBinder token,boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) @ActivityThread.java{//从之前保存的arraymap中获取 ActivityClientRecord。ActivityClientRecord r = mActivities.get(token);//这个调用会执行Activity的onResume函数的调用。r = performResumeActivity(token, clearHide, reason);final Activity a = r.activity;if (r.window == null && !a.mFinished && willBeVisible) {//Activity对应的窗口,最外围的DecorView。r.window = r.activity.getWindow();View decor = r.window.getDecorView();decor.setVisibility(View.INVISIBLE);//这里的wm实际是WindowManagerImpl对象。ViewManager wm = a.getWindowManager();//指定窗口属性是 TYPE_BASE_APPLICATION。l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;}//把viewtree注册到WMS。if (a.mVisibleFromClient && !a.mWindowAdded) {a.mWindowAdded = true;wm.addView(decor, l);}}
WindowManagerImpl的addView方法,直接调用WindowManagerGlobal中的方法。
public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow) @WindowManagerGlobal.java{ViewRootImpl root;View panelParentView = null;//检查之前是否已经添加过。int index = findViewLocked(view, false);//为这个view生成一个 ViewRootImpl对象。root = new ViewRootImpl(view.getContext(), display);//添加到本地的全局变量中,即那三个列表, mViews记录DecorView, mRoots记录ViewRootImpl, mParams记录布局属性。view.setLayoutParams(wparams);mViews.add(view);mRoots.add(root);mParams.add(wparams);//通过Viewrootimpl的 setView把DecorView记录到ViewRootImpl中的变量mView中,ViewRootImpl后期做事件传递时会把事件传到mView中处理。这样ViewTree就创建完成了,后面接着的是向WMS申请显示窗口(当然这个显示窗口不是phoneWindow),可以认为是一个surface 是一个layer。root.setView(view, wparams, panelParentView);}
阅读全文
0 0
- Android GUI系统-ViewTree的创建(二)
- Android GUI系统-ViewTree的管理者(三)
- Android GUI系统-ViewTree的遍历(四)
- Android 的GUI 系统
- Android 的GUI 系统
- Android 的GUI 系统
- Android 的GUI 系统
- android 的View Tree和 DecorView(Android ViewTree and DecorView)
- Android ViewTree and DecorView
- Android ViewTree and DecorView
- Android 的GUI 系统结构
- viewTree
- Android---手动创建线程与GUI线程同步(二)
- Android 7.1 GUI系统-BufferQueue 的管理(三)
- Android 7.1 GUI系统-vsync信号的处理(六)
- Android 7.1 GUI系统-窗口管理WMS-窗口属性(二)
- JAVA 程序设计(二十八)窗体的创建设计如下GUI界面
- Android 7.1 GUI系统-surfaceflinger(四)
- 基于freertos的xTaskUntilDelay函数问题解析
- 探索 ConcurrentHashMap 高并发性的实现机制
- 希尔排序,选择排序,插入排序 java
- Win10与ubuntu双系统,卸载ubuntu后,出现no such partition 后的修复办法
- 【java基础:JDBC】基于DPCP连接池工具包和DBUtils工具包的数据库改查Demonstration
- Android GUI系统-ViewTree的创建(二)
- 正则表达式(Java版整理)
- 这是我的第一篇博客,以后要积极更新哦
- Mysql 充电站SQL查询1--171221--mysql-sql
- 破解简单的Android签名检查
- 堆排序
- es6快速入门(4)--数组的扩展
- Python--小甲鱼学习笔记--第26课:字典(dict())
- 446. Arithmetic Slices II