原文链接: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();

    Activity a = 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)) {                throw new RuntimeException(                    "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 = new Configuration(mCompatConfiguration);                if (r.overrideConfig != null) {                    config.updateFrom(r.overrideConfig);                }                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "                        + r.activityInfo.name + " with config " + config);                Window window = 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);                           }          ...       }            return activity;    }

这个方法主要是读取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 = new PhoneWindow(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构造方法。

public PhoneWindow(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.        boolean forceResizable = 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/

更多相关文章

  1. android Activity活动周期 Service生命周期
  2. [Android] Android使用序列化接口Parcelable、Serializable
  3. Android开机自动启动Wi-Fi热点的方法
  4. Android(安卓)进阶学习:事件分发机制完全解析,带你从源码的角度彻
  5. Android(安卓)中的 Service 全面总结
  6. Android——横屏和竖屏的切换,以及明文密码的显示
  7. Android实例剖析笔记(三)
  8. android bionic缺失pthread_cancel的解决方法
  9. Android四大组件之Activity---生命周期那些你可能不知道的事

随机推荐

  1. Android:UI设置-横竖屏转换、输入法键盘相
  2. Android的Thread & ProgressBar
  3. Android:Debug certificate expired on D
  4. android预定义样式
  5. android 塔防游戏汇总 及android 游戏开
  6. Android(安卓)requires compiler complia
  7. android中读写sd卡文件
  8. Android: Support Libraries for Android
  9. android中使用wakelock
  10. android studio 加载.proto不能生成xxxDr