• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

Android绘制流程窗口启动流程分析上

android 搞代码 3年前 (2022-03-02) 15次浏览 已收录 0个评论

源码剖析篇 – Android绘制流程(一)窗口启动流程剖析

Activity、View、Window之间的关系能够用以下的简要UML关系图示意,在这里贴出来,比拟可能帮组前面流程剖析局部的浏览。

一、Activity的启动流程

在startActivity()后,通过一些逻辑流程会告诉到ActivityManagerService(前面以AMS简称),AMS接管到启动acitivty的申请后,会通过跨过程通信调用AcitivtyThread.handleLauncherActivity()办法,咱们从这里开始剖析,首先来看handleLauncherActivity()办法。

\`private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {

...// Initialize before creating the activity

WindowManagerGlobal.initialize();

Activitya = performLaunchActivity(r, customIntent);

if (a != null) {         r.createdConfig = new Configuration(mConfiguration);         reportSizeConfigurations(r);         Bundle oldState = r.state;

//该办法会调用到Activity的onResume()办法         handleResumeActivity(r.token, false, r.isForward,               !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

...

}

...

}\`

这里重点关注三个办法(加粗的中央),首先来看WindowManagerGlobal.initialize(),WindowManagerGlobal是单例模式的,一个过程内只有一个,这里调用该类的初始化办法,后续咱们再对该类的作用和相干办法进行剖析;第三个是在创立好Activity后调用Acitivty的onResume()办法。这里咱们来看需关注的第二个办法performLaunchActivity(),代码如下。

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {      ...//通过反射形式创立Activity        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);            r.intent.prepareToEnterProcess();if(r.state !=null) {                r.state.setClassLoader(cl);            }        }catch(Exception e) {if(!mInstrumentation.onException(activity, e)) {thrownewRuntimeException("Unable to instantiate activity "+ component                    +": "+ e.toString(), e);            }        }try{            ...if(activity !=null) {                Context appContext = createBaseContextForActivity(r, activity);                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());                Configuration config =newConfiguration(mCompatConfiguration);if(r.overrideConfig !=null) {                    config.updateFrom(r.overrideConfig);                }if(DEBUG\_CONFIGURATION) Slog.v(TAG,"Launching activity "+ r.activityInfo.name +" with config "+ config);                Windowwindow=null;if(r.mPendingRemoveWindow !=null&& r.mPreserveWindow) {window= r.mPendingRemoveWindow;                    r.mPendingRemoveWindow =null;                    r.mPendingRemoveWindowManager =null;                }                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);            ...//调用acitivity的onCreate()办法if(r.isPersistable()) {                                   mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);                           }else{                                   mInstrumentation.callActivityOnCreate(activity, r.state);                           }          ...       }returnactivity;    }

这个办法次要是读取Acitivity这里利用反射创立出ActivityClientRecord所要求的Activity对象,而后调用了acitivity.attach()办法。留神attach()传入的参数有很多,在performLacunchActivity()办法流程中,调用attach()方前,咱们省略掉的步骤根本都在为这些参数做筹备,attach()办法的作用其实就是将这些参数配置到新创建的Activity对象中;而在attach之后则会回调到acitivity的onCreate()办法。咱们进入Activity.java类具体来看下attach办法。

此外,在attach之前会初始化一个Window对象,Window.java是一个抽象类,代表了一个矩形不可见的容器,次要负责加载显示界面,每个Activity都会对应了一个Window对象。如果ActivityClientRecord.mPendingRevomeWindow变量中曾经保留了一个Window对象,则会在前面的attach办法中被应用,具体应用的场景会在前面中介绍。

`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, String referrer, IVoiceInteractor voiceInteractor,

Window window) {

attachBaseContext(context);

mFragments.attachHost(null/*parent*/);    mWindow =newPhoneWindow(this,window);//(1)mWindow.setWindowControllerCallback(this);    mWindow.setCallback(this);    mWindow.setOnWindowDismissedCallback(this);    mWindow.getLayoutInflater().setPrivateFactory(this);if(info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {        mWindow.setSoftInputMode(info.softInputMode);    }if(info.uiOptions !=0) {        mWindow.setUiOptions(info.uiOptions);    }     …//初始化Acitity相干属性mWindow.setWindowManager(            (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),            mToken, mComponent.flattenToString(),            (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) !=0);//(2)if(mParent !=null) {        mWindow.setContainer(mParent.getWindow());    }    mWindowManager = mWindow.getWindowManager();    mCurrentConfig = config;}`

 重点关注初始化window对象的操作,首先创立了PhoneWindow对象为activity的mWindow变量,在创立时传入了上一个activity对应的window对象,之后又将这个acitivity设置为window对象的回调。Activity中很多操作view相干的办法,例如setContentView()、findViewById()、getLayoutInflater()等,实际上都是间接调用到PhoneWindow外面的相干办法。创立完acitivty对应的PhoneWindow之后便会调用setWindowManager()办法。首先来看PhonewWindow构造方法。

publicPhoneWindow(Context context, Window preservedWindow){this(context);// Only main activity windows use decor context, all the other windows depend on whatever// context that was given to them.mUseDecorContext =true;if(preservedWindow !=null) {//疾速重启activity机制mDecor = (DecorView) preservedWindow.getDecorView();            mElevation = preservedWindow.getElevation();            mLoadElevation =false;            mForceDecorInstall =true;// If we're preserving window, carry over the app token from the preserved// window, as we'll be skipping the addView in handleResumeActivity(), and// the token will not be updated as for a new window.getAttributes().token = preservedWindow.getAttributes().token;        }// Even though the device doesn't support picture-in-picture mode,// an user can force using it through developer options.booleanforceResizable = Settings.Global.getInt(context.getContentResolver(),                DEVELOPMENT\_FORCE\_RESIZABLE\_ACTIVITIES,0) !=0;        mSupportsPictureInPicture = forceResizable || context.getPackageManager().hasSystemFeature(                PackageManager.FEATURE\_PICTURE\_IN\_PICTURE);    }

搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Android绘制流程窗口启动流程分析上

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址