原文链接:https://www.cnblogs.com/tiger-wang-ms/p/6517048.html
源码剖析篇 – 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); }
点击下方链接收费获取 Android 进阶材料:
https://shimo.im/docs/tXXKHgdjPYj6WT8d/