《Android源代码系统情景分析》读书笔记 (1) Activity组件启动过程

来源:互联网 发布:蚂蚁系统分类数据调用 编辑:程序博客网 时间:2024/05/17 06:09

前言

  • 换公司后将近2个月没有更新过博客呢,很大一部分原因是因为平时下班都太晚了.回来看会英语都12点了,实在没法像以前在成都每晚回来又那么充裕的时间写东西.
  • 最近,在新公司学习了一些性能代码优化的小技巧,例如traceview,MAT,systrace等的使用,这些在网上都有很多资料可以查询,这里就不赘述了.最近利用周末时间撸了两个库,虽然都是重复造轮子,但收获还是蛮大的.最近打算整理下,写出来.
  • 不过今天打算写下android源码的读书笔记,这个笔者在之前面试的时候,深知此的重要性.以及在最近做app冷启动优化的时候,也涉及到了,Activity组件启动过程.熟知原理才知如何具体去精确改善.
  • “纸上得来终觉浅,绝知此事要躬行”.望共勉

正文

  • Activity两种类型:
    1.根Acivtity,以快捷图片的形式显示在应用程序启动器中
    2.子Activity.分别可以运行在同一或者不同一进程中.
  • 启动方式:
    1.显式启动,需知道类名
    2.隐式启动,可以减少activity组件之间的依赖.

Activity同进程启动(lancher启动,栈内启动),Activity跨进程启动

  • Lancher启动Activity:
    概述:Lancher组件通过调用ActivityManagerService来启动MainActivity,这三个组件运行在三个进程中.调用方法涉及到Binder机制通信.

  • Lancher中执行的:
    →调用startActivitySafely(在NEW_TASK中启动)
    →调用startActivity
    →调用startActivityForResult(-1),表明不需要回调
    →调用IntruMentation.execStartActivity,作用:传递成员变量mToken(也就是IBinder)传递给ActivityManagerService,这样ActivityManagerService就可以获取到Lancher组件的详细信息了.
    →调用ActivityManagerNative.getDefault().startActivity(),作用:获取ActivityManagerService一个代理对象来通知ActivityManagerService将一个组件启动起来.
    →调用ActivityManagerProxy.startActivity().作用:将传递参数写入到Parcel对象data中,向ActivityManagerService发送一个START_ACTIVITY_TRANSACTION进程间通信请求.

  • ActivityManagerService中执行的:
    →调用ActivityManagerService.startActivity();作用:mMainStack.startActivityMayWait()来进一步处理类型为START_ACTIVITY_TRANSACTION的进程间通信请求.
    →调用ActivityStack.startActivityMayWait(),作用:PackageManagerService来解析Intent传递的内容,并且保存到ActivityInfo对象中,在调用startActivityLocked来继续执行启动Activity组件的工作.
    →调用ActivityStack.startActivityLocked,作用:每一个进程都用ProcessRecord来描述,通过ActivityManagerService.getRecordForAppLocked来获取caller,也就是ApplicationThread对象得到进程的pid和uid,每一个启动的Activity组件都会使用一个ActivityRecord来描述.到这一步以及得到源Activity和要启动目标Activity的相关信息了,然后就是调用ActvityStack.startActivityUncheckedLocked.
    →调用ActvityStack.startActivityUncheckedLocked,作用:获取activity的flag标记,ActivityManagerService会检查目标Activity组件的专属任务是否存在,如果已经存在,会直接添加进去运行,否则就会先创建这个专属任务,然后在将目标Activity组件添加到里面再运行.
    →调用startActivityLocked来执行启动目标Activity组件的操作,作用:其实就是调用ActivityStack栈来进行管理要启动的activity,把它放到栈顶
    →调用ActvityStack.resumeTopActivityLocked ,这个也是判断当前Activity组件堆栈最上面的一个不是处于结束状态的Activity组件,最后调用ActivityStack.startPausingLocked来通知它进入Pause状态,以便它可以将焦点让给即将要启动的MainActivity组件。
    →调用ActvityStack.startPausingLocked,这个方法做了两件事,第一,将ActivityRecord对象prev指向即将要进入Paused状态的lancher组件,最后在通过ActivityManagerService发送一个启动MainActivity组件的延迟通知。
    接上一个方法,调用了ApplicationThreadProxy.scheldulePauseActivity,将前面写进来的参数,写入Parcel对象中,然后在通过ApplicationThreadProxy类内部的一个Binder代理对象向lancher组件所在的进程发送一个进程间通信的请求。并且这个进程间通信是异步的。
    AppplicationThread.schedulePauseActivity是用来处理进程间通信的。之后会调用ActivityThread.queueOrSendMessage来向lancher的主线程的消息队列发送一个消息。
    ActivityThread.queueOrSendMessage,这个是应用程序进程的主线程调用handleMessage来处理中止Lancher组件的操作。
    AticivtyThread.H,接收到的message对象会强转成Ibinder接口,在调用handlePauseActivity来处理类型为PAUSE_ACTIVITY的消息。

    ActivityThread.handlePauseActivity,ActivityClientRecord对象对于ActivityMessagerService中的ActivityRecord对象。1.获取要中止的Activity组件, 2.调用performUserLeavingAcitity的Lancher组件发送一个用户离开事件通知,即调用它的成员函数onUserLeaveHint. 3.调用performPauseActivity向lancher组件发送一个中止事件通知,即调用它的成员函数onPause. 4.QueuedWork.waitToFinish等待完成前面的一些数据写入操作。5.获取ActivityManagerService一个代理对象,通过activityPaused这个方法,来通知ActivityManagerService,lancher组件已经进入Pause状态,然后它可以将MainActivity组件启动起来了。
    ActivityManagerProxy。activityPause,又是通过类内部的一个Binder代理对象想ActivityManagerService发送一个进程间通信的请求。
    ActivityManagerService.activityPaused,调用activityPaused来处理该进程通信的请求。
    ActivityStack.ativityPaused , 1.在Aticitvy组件堆栈中找到与Lancher组件对应的ActivityRecord对象。2.确认Lancher组件进入Paused状态后,在通过completePauseLocked来执行启动MainActivity的操作
    ActivityStack.completePauseLocked , 1.先确定当前正在中止的Activity组件已经进入Paused状态了,2. 调用resumeTopActivityLocked来启动位于Activity栈顶端的Activity组件。
    ActivityStack.resumeTopActivityLocked, 1.调用topRunningActivityLocked获取位于Activity组件堆栈顶端的与即将启动的MainActivity组件对应的一个ActivityRecord对象, 2.调用startSpecialficActivityLocked将它启动起来。
    ActivityStack.startSpecialficActivityLocked, AcitivityManagerService在启动一个Activity组件时,会以他的用户id和进程名来检查是否存在。如果存在就调用realStartActivityLocked来启动该Activity组件,否则就调用ActivityManagerService.startProcessLocked为该组件创建一个进程并将它启动起来。
    ActivityManagerService.startProcessLocked , 1.先创建一个ProcessRecord对象,然后在调用startProcessLocked来创建一个应用程序进程。
    ActivityThread.main , 新引用程序进程在启动时,主要做了两件事。 1. 创建ActivityThread对象,通过attach 向 ActivityManagerService发送一个启动完成的通知 . 2. 调用Looper.prepareMainLooper创建一个消息循环,并且在向ActivityManagerService发送启动完成通知后,使得当前进程进入这个消息循环中。
    ActivityManagerProxy.attachApplication , 向activityManagerService发送一个进程通信请求。
    ActivityManager.attachApplication , 调用attachApplicationLocked来继续启动MainActivity组件的操作。
    ActivityManager.attachApplicationLocked , 调用ActivityStack.realStartActivityLocked来请求该应用程序进程启动一个Activity组件。
    ActivityManager.realStartActivityLocked , 调用ApplicationThreadProxy.scheduleLanchActivity来向前面创建的应用程序进程发送一个进程间通信的请求。
    ApplicationThreadProxy.scheduleLanchActivity , 向activityManagerService发送一个进程通信请求。
    ApplicationThread.scheduleLanchActivity , 作用; 将要启动的Activity组件的信息封装成一个ActivityClientRecord对象, 然后来调用queueOrsendMessage , 往新创建应用程序进程的主线程的消息队列发送一个消息、
    ApplicationThread。queueOrsendMessage , 发送的消息最终的处理 在 AtciityThread.mH.handleMessage中处理的。
    H.handleMessage , 调用ActivityThread.handleLaunchActivity来启动MainActivity.
    ActivityThread.handleLaunchActivity , 1.先通过performLaunchActivity将MainActivity启动起来。 2.handleResumeActivity将MainActivity状态设置为Resuemed.
    ActivityThread.performLaunchActivity , 1.ContextImpl来初始context, 2.使用context和ActivityClientRecord来初始化Activity. 3.调用MainActivity的onCreate.
    MainActivity.onCreate , MainActivity启动完成

0 0
原创粉丝点击