Android源码个个击破之Context和Activity的启动流程-创新互联

Activity 中mParent 成员变量是如何被赋值的。 - CSDN博客

我们提供的服务有:网站设计制作、成都网站设计、微信公众号开发、网站优化、网站认证、集贤ssl等。为上1000家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的集贤网站制作公司
  • Android 视图渲染过程的源码分析 - CSDN博客

  • android系统启动框架、Activity界面显示过程详解 - snow_flower - 博客园

  • Android源码之Activity从启动到显示到界面 - 阿里云

以下的源码都是API26.

context的初始化过程:https://www.jianshu.com/p/7d4b605f5060

----------------------------------------------------------------------------------------------------------------------------------------------

    系统级别的Context实例化过程:

SystemServer的run方法中,调用createSystemContext方法

Android源码个个击破之Context和Activity的启动流程

1)systemMain方法

    通过ActivityThread的systemMain方法创建了一个系统级别的ActivityThread

Android源码个个击破之Context和Activity的启动流程

调用activityThread的attach方法,传入true。

该方法创建了application并调用了onCreate方法。

   Android源码个个击破之Context和Activity的启动流程

  2)getSystemContext()

  Android源码个个击破之Context和Activity的启动流程

 Android源码个个击破之Context和Activity的启动流程

  以上是系统级别的context实例化过程,为了弄清activity这个context是如何实例化的,就得研究一下activity的启动过程。https://blog.csdn.net/qq_23547831/article/details/51224992

  需要注意的是activity,service启动activity的过程都各不一样,activity复写了startActivity方法,service直接调用了父类的方法。

 activity之所以要复写startActivity方法,是为了复用activity独有的startActivityForResult方法。

  最终都会调用到Instrumentation的启动activity方法,再调用ActivityManagerNative

  Android源码个个击破之Context和Activity的启动流程

 

Android源码个个击破之Context和Activity的启动流程

 很明显,启动activity使用了binder。

    这个"activity"为key的service是何时添加的呢?

    我尝试着在SystemServer里找,但是没有找到。在ActivityManagerService自身的代码里找到。而setSystemProcess在SystemServer里被调用。

   Android源码个个击破之Context和Activity的启动流程

Android源码个个击破之Context和Activity的启动流程

 

ActivityManagerService的实例是怎么创建出来的呢?

Android源码个个击破之Context和Activity的启动流程

Android源码个个击破之Context和Activity的启动流程

 

上面根据字节码反射创建了service的实例,实例实际是ActivityManagerService的内部类:Lifecycle.

Android源码个个击破之Context和Activity的启动流程

Android源码个个击破之Context和Activity的启动流程

调用了Android源码个个击破之Context和Activity的启动流程

getService方法得到了真正的ActivityManagerService.

Android源码个个击破之Context和Activity的启动流程

调用了service的onStart方法。

上面说了这么多,关于ActivityManagerService创建的过程。      

但是疑问尚在:

1)activity怎么就具备了context的特性了,它也没有new,怎么使之成为一个context。

2)startActivity怎么android系统就会弹出一个界面

前面Android源码个个击破之Context和Activity的启动流程

开启activity,最终会通过Binder机制(数据传输机制比较麻烦,后面研究)跨进程调用

ActivityManagerServcie的startActivityAsUser方法:

Android源码个个击破之Context和Activity的启动流程

继而调用ActivityStarter的startActivityMayWait方法

Android源码个个击破之Context和Activity的启动流程

在方法中又会调用到startActivityLocked方法

Android源码个个击破之Context和Activity的启动流程

方法最后会调用到 startActivityUnchecked方法

Android源码个个击破之Context和Activity的启动流程

最终调用了ActivityStack的startActivityLocked方法:

Android源码个个击破之Context和Activity的启动流程

注意下面这部分代码,不同版本的源码会有很大的区别。

1)首先判断开启的activity是否是新任务,分别做不同的处理。

Android源码个个击破之Context和Activity的启动流程

2)主要是调用WindowManager

***准备事务

***添加token

Android源码个个击破之Context和Activity的启动流程

调用WindowManagerService的H来发送消息

Android源码个个击破之Context和Activity的启动流程

注意ensureActivitiesVisibleLocked这个方法

Android源码个个击破之Context和Activity的启动流程

接着方法调用顺序:

makeVisibleAndRestartIfNeeded (ActivityStack)

startSpecificActivityLocked (ActivityStackSupervisor)

realStartActivityLocked (ActivityStackSupervisor)

此方法内部会调用 app.thread.scheduleLaunchActivity,这个app.thread是IApplicationThread类的实例,具体的子类是哪个呢?

下面的源码为API26

app即Proce***ecord类

Android源码个个击破之Context和Activity的启动流程

在里面搜索thread的set方法:
  Android源码个个击破之Context和Activity的启动流程

makeActive点击发现有2处引用:

引用1:

Android源码个个击破之Context和Activity的启动流程

Android源码个个击破之Context和Activity的启动流程

Android源码个个击破之Context和Activity的启动流程

引用2:

Android源码个个击破之Context和Activity的启动流程

找到上一个调用的地方

Android源码个个击破之Context和Activity的启动流程

Android源码个个击破之Context和Activity的启动流程

由上面的分析可知:app.thread的thread是ActivityThread

下面看它的scheduleLaunchActivity方法,看它是如何启动Activity的:

1)发送消息给H这个Handler

Android源码个个击破之Context和Activity的启动流程

注意这个r变量,在后面有关Activity渲染绘制的源码中会用到。

2)handler的处理

Android源码个个击破之Context和Activity的启动流程

实例化了Activity的对象:

Android源码个个击破之Context和Activity的启动流程

通过Instrumentation的newActivity方法创建了Activity的实体:
  Android源码个个击破之Context和Activity的启动流程

Android源码个个击破之Context和Activity的启动流程

尝试创建Application

Android源码个个击破之Context和Activity的启动流程   

下面的代码说明了Application只存在一个实例。

Android源码个个击破之Context和Activity的启动流程

接着看performLaunchActivity方法:

Android源码个个击破之Context和Activity的启动流程

Android源码个个击破之Context和Activity的启动流程

将ContextImpl对象通过Activity的attach方法传入到Activity

Android源码个个击破之Context和Activity的启动流程

Android源码个个击破之Context和Activity的启动流程

Android源码个个击破之Context和Activity的启动流程

最后这个也说明了ContextWrapper里的mBase是对ContextImpl。

看官方对ContextWrapper类解释:

Android源码个个击破之Context和Activity的启动流程

英文的意思是说ContextWrapper是对Context的一种代理实现。

#Activity的onCreate方法回调

Android源码个个击破之Context和Activity的启动流程

Android源码个个击破之Context和Activity的启动流程

下面我们来细抠Activity的onCreate方法:

@MainThread
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
    if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);

    if (getApplicationInfo().targetSdkVersion > O && mActivityInfo.isFixedOrientation()) {
        final TypedArray ta = obtainStyledAttributes(com.android.internal.R.styleable.Window);
        final boolean isTranslucentOrFloating = ActivityInfo.isTranslucentOrFloating(ta);
        ta.recycle();

        if (isTranslucentOrFloating) {
            throw new IllegalStateException(
                    "Only fullscreen opaque activities can request orientation");
        }
    }

    if (mLastNonConfigurationInstances != null) {
        mFragments.restoreLoaderNonConfig(mLastNonConfigurationInstances.loaders);
    }
    if (mActivityInfo.parentActivityName != null) {
        if (mActionBar == null) {
            mEnableDefaultActionBarUp = true;
        } else {
            mActionBar.setDefaultDisplayHomeAsUpEnabled(true);
        }
    }
    if (savedInstanceState != null) {
        mAutoFillResetNeeded = savedInstanceState.getBoolean(AUTOFILL_RESET_NEEDED, false);
        mLastAutofillId = savedInstanceState.getInt(LAST_AUTOFILL_ID,
                View.LAST_APP_AUTOFILL_ID);

        if (mAutoFillResetNeeded) {
            getAutofillManager().onCreate(savedInstanceState);
        }

        Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
        mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
                ? mLastNonConfigurationInstances.fragments : null);
    }
    mFragments.dispatchCreate();
    getApplication().dispatchActivityCreated(this, savedInstanceState);
    if (mVoiceInteractor != null) {
        mVoiceInteractor.attachActivity(this);
    }
    mCalled = true;
}
  • mFragments.dispatchCreate() :将onCreate事件分发给fragment,至于具体怎么分发的,后面再研究。

  • getApplication().dispatchActivityCreated(this, savedInstanceState) :这个方法是将activity的生命周期方法回调给Application

    Android源码个个击破之Context和Activity的启动流程

   

    在Application里即可利用这2个方法来监听activity的状态:

    Android源码个个击破之Context和Activity的启动流程

这样,不需要通过广播,就能监听到Activity的生命周期方法了。(所以不阅读源码,很多好用的东西发现不了!)

    • Activity的onCreate方法里会有一个mCalled变量,来判断程序员复写onCreate方法是否调用了super.onCreate方法。

紧接着onCreate,又调用了onStart等其它的生命周期方法。

    所以Activity初始创建的生命周期方法调用顺序是:

  • attach

  • onCreate
    onStart

  上面我们的注重点在于activity是如何实例化的,下面来研究一下UI方面的:Activity是怎么弹出并展示到我们的眼前的呢

  请看  Android源码个个击破之Activity的渲染过程

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


本文名称:Android源码个个击破之Context和Activity的启动流程-创新互联
URL地址:http://scyanting.com/article/dischd.html