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

发布时间:2020-07-07 12:31:14 作者:屠夫章哥
来源:网络 阅读:925

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



以下的源码都是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;
}

       

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

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

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


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

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

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

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


  


推荐阅读:
  1. Android源码个个击破之-多媒体扫描
  2. Android源码个个击破之拨号源码

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

android 源码 roi

上一篇:趋势OFFICESCAN忘记卸载密码时如何卸载客户端

下一篇:网络骇客入门之网络编程(一):网络应知应会

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》