Android系统各个流程运行方法总结

学习编程 2018-01-26

Zygote的启动过程

1.系统启动init进程时会启动Zygote进程(负责Android运行时进程和应用进程的启动)
2.Zygote进程会首先启动SystemServer进程,SystemServer进程会启动系统的关键服务(PMS和AMS)
3.当启动应用程序时,AMS通过socket向Zygote通知创建新的进程

Android应用程序安装过程

  • 系统启动安装过程
  1. SystemServer进程启动PackageManagerService服务实例,添加到ServiceManager(负责管理系统中的Binder对象)

  2. PackageManagerService.main()扫描指定目录的apk归档文件

/system/framework
/system/app
/vendor/app
/data/app
/data/app-private
  1. 对apk文件解析AndroidManifest.xml各个标签,得到的package、provider、service、receiver和activity等信息保存在PackageManagerService服务的内存中。
  • 下载安装过程下载apk->拷贝到指定目录->解析apk归档文件的AndroidManifest.xml的应用程序的信息到packageManagerServices中#应用程序启动流程
  1. Launcher通过Binder进程间通信机制通知ActivityManagerService,它要启动一个Activity;
  2. ActivityManagerService通过Binder进程间通信机制通知Launcher进入Paused状态;
  3. Launcher通过Binder进程间通信机制通知ActivityManagerService,它已经准备就绪进入Paused状态,于是ActivityManagerService就创建一个新的进程,用来启动一个ActivityThread实例,即将要启动的Activity就是在这个ActivityThread实例中运行;
  4. ActivityThread通过Binder进程间通信机制将一个ApplicationThread类型的Binder对象传递给ActivityManagerService,以便以后ActivityManagerService能够通过这个Binder对象和它进行通信;
  5. AMS通知ActivityThread对象中调用bindApplication()方法. 送到消息队列中, 最终通过handleBindApplication()方法处理该消息. 然后调用makeApplication()方法来加载Application的classes到内存中,然后通知AMS。
  6. ActivityManagerService通过Binder进程间通信机制通知ActivityThread,可以真正执行Activity的启动。

Launcher启动过程

  1. SystemServer进程启动ActivityManagerService服务实例,添加到ServiceManager(负责管理系统中的Binder对象)
  2. ActivityManagerService向PackageManagerService查询Category类型为HOME的Activity,通过 ActivityStack.startActivityLocked将Launcher启动起来
  3. Launcher在onCreate()中,通过这个PackageManagerService.queryIntentActivities接口来取回所有Action类型为Intent.ACTION_MAIN,并且Category类型为Intent.CATEGORY_LAUNCHER的Activity。显示这些到页面上。

Activity启动流程

  1. AMS创建新进程,创建ActivityThread实例,将ApplicationThread的Binder对象传递给AMS并且开始了消息循环。
  2. 从新进程调用到ActivityManagerService进程中,获取要在新进程启动的服务的相关信息;
  3. 从ActivityManagerService进程又回到新进程中,最终将服务启动起来。
    3.1. performLaunchActivity()初始化Activity
     3.1.1 classLoader加载Activity类,mInstrumentation.newActivity实例化Activity
     3.1.2 makeApplication如果进程中没有就重新创建
     3.1.3 Activity.attach()将上下文信息设置到Activity中 包括window创建
     3.1.4 mInstrumentation.callActivityOnCreate->onCreate()调用setContentView为decorView设置页面内容
     3.1.5 Instrumentation.callActivityOnStart->onStart() 初始化应用数据准备
    3.2 handleResumeActivity激活Activity
     3.2.1 mInstrumentation.callActivityOnResume->onResume()做准备显示到交互的处理
     3.2.2 wm.addView添加window的decorView开始绘制显示页面交互

Service启动流程

service将计算型的逻辑单独放在一个进程内执行提高用户体验。

start流程

  1. AMS创建新进程(会判断ProcessRecord不存在才去创建),创建ActivityThread实例,将ApplicationThread的Binder对象传递给AMS并且开始了消息循环。
  2. 从新进程调用到ActivityManagerService进程中,获取要在新进程启动的服务的相关信息;
  3. 从ActivityManagerService进程又回到新进程中,最终将服务启动起来。
    3.1 handleCreateService()初始化Service
     3.1.1 通过ClassLoader加载service类,然后的newInstance实例化Service
     3.1.2 makeApplication如果进程中没有就重新创建
     3.1.3 service.attach() 上下文信息设置到service中
     3.1.4 service.onCreate()回调
  4. 然后还会回新进程ApplicationThread.scheduleServiceArgs在主线程中回调onStartCommand

bind流程

  1. MainActivity调用bindService函数通知ActivityManagerService,它要启动CounterService这个服务,ActivityManagerService于是在MainActivity所在的进程内部把CounterService启动起来,并且调用它的onCreate函数;
  2. ActivityManagerService把CounterService启动起来后,继续调用CounterService的onBind函数,要求CounterService返回一个Binder对象给它;
  3. ActivityManagerService从CounterService处得到这个Binder对象后,就把它传给MainActivity,即把这个Binder对象作为参数传递给MainActivity内部定义的ServiceConnection对象的onServiceConnected函数;
  4. MainActivity内部定义的ServiceConnection对象的onServiceConnected函数在得到这个Binder对象后,就通过它的getService成同函数获得CounterService接口。

PhoneWindow流程

  1. 在Activity的attach中创建PhoneWindow并完成相关设置
    1.1 调用PolicyManager.makeNewWindow创建PhoneWindow,
    1.2 设置window的Calback将IO输入事件分发给Activity(softMode设置)
    1.3 设置windowManager,mAppToken为ActivityManagerService侧ActivityRecord(Binder对象),mAppName为Activity组件名称
  2. 在onCreate中的setContentView(rId)完成window的视图内容的设置
    2.1 installDecor()根据Theme和Feature完成window的顶级视图mDecor以及找到mContentParent
    2.2 通过mLayoutInflater.inflate(layoutResID, mContentParent)设置到mContentParent中
  3. 在handleResumeActivity()中wm.addView()将window的内容绘制出来
    3.1 WindowManagerImpl.addView将decorView、viewRoot、LayoutParamas分别添加到mViews[i]、mRoots[i]和mParams[I]中
    3.2 viewRootImpl.setView()完成相关成员的配置工作和绘制
     3.2.1 将decorView设置到mAttachInfo.mRootView上
     3.2.2 panelParentView不为空表示window是子窗口,需要保存ApplicationWindowToken到mAttachInfo中
     3.2.3 调用requestLayout()执行view树的绘制流程

View绘制流程

  1. viewRootImpl的requestLayout()和invalidateChildInParent()最终都调用performTraversals()开始执行测量、布局、绘制
  2. mView.measure测量所有view的宽高这里就比按照流程叙述了,按照我自己的通俗的理解来讲
    前言:view测量时有限制MeasureSpec。自己的申请(layout_)告诉父亲,父亲根据自己的情况计算家里的情况给出的钱(空间)的使用限制。Mode:家里的情况,Size:到手钱自己当爸爸了 viewGroup(详情getChildMeasureSpec)
家里的情况 Mode,拿到手上有 size大小的钱
  1.不管家里任何情况,只要儿子申请花调固定的数字childDimension>=0,超过限制也给,
儿子的Mode=EXACTLY,Size=childDimension
  2.其他的话看家里情况
            都用掉 EXACTLY: 
                  儿子申请都给我吧 MATCH_PARENT:目标明确,给。儿子的Mode=EXACTLY,Size=size
                  儿子申请我自己算 WRAP_CONTENT:儿子的Model=AT_MOST,Size=size
        家里手头紧不能超过 AT_MOST:
                  不管儿子申请 MATCH_PARENT 还是 WRAP_CONTENT:告诉子孙们手头紧Mode=AT_MOST,Size=size
         不知道啥情况,但是手动有钱 UNSPECIFIED:
                 不管儿子申请 MATCH_PARENT 还是 WRAP_CONTENT:告诉子孙们家里不知道啥情况Mode=UNSPECIFIED,Size=size

自己绝育了View,祖宗传下来过日子之法 (详情resolveSize)

看家里情况
            要你都用掉 EXACTLY: 
                  都用光
        家里手头紧不能超过 AT_MOST:
                  自己用多少算多少吧,不超过就行
         不知道啥情况,但是手动有钱 UNSPECIFIED:
                   没限制,自己用多少算多少
  1. mView.layout 递归View树 根据viewGroup的layout规则设置所有子View的位置
    3.1 ViewGroup必须重写onLayout,根据排列规则以及measure测量的宽高调用child.layout对子View进行设置
    3.2 View的layout中调用setFrame完成对mLeft、mTop、mRight和mBottom赋值
    总结:所有的View都得靠父布局通过自己的margin等相对规则确定位置
  2. mView.draw 递归View树绘制所有view到canvas上
    4.1 draw()控制整体绘制流程,可被重写
    4.2 drawBackground()绘制背景,不可被重写
    4.3 ondraw()绘制主体,可被重写
    4.4 dispatchDraw() 主要给ViewGroup重写分配给子View绘制,可重写
    4.5 绘制滚动条和前景 在6.0合并到onDrawForeground(),可被重写

ps:其实还有一个draw被ViewGroup通过drawChild调用,这个draw拿到的canvas是完整的父View的canvas,应用view动画的矩阵之后在整个canvas里裁剪对应view位置和大小的一块canvas交给处理view自身绘制流程的draw方法

应用事件分发流程

通过View树传递触摸事件,一旦有View消费掉事件就不会继续向下传递,如果没有消费掉就会往上抛交给父View处理。down事件被View消费之后,后面连续的事件都会交给它处理。

  • Activity事件分发
  1. phoneWindow将事件回调Activity的dispatchTouchEvent()分发事件
  2. 如果Event是ACTION_DOWN的情况下会接着触发onUserInteraction方法。
  3. 分发给mContentParent的子View处理事件
  4. 若子view拦截了事件(返回true)则Activity.onTouchEvent方法就不会执行。
  • ViewGroup事件分发
  1. dispatchTouchEvent 分发处理事件
  2. 通过disallowIntercept先判断子View是否不让ViewGroup拦截事件
  3. onInterceptTouchEvent()判断当前ViewGroup是否需要拦截该事件
  4. 不拦截就直接dispatchTransformedTouchEvent()分发给子View处理,如果子View没有处理就继续交给自己逻辑
  5. 拦截就交给自己处理,交给super.dispatchTochEvent()处理
  • View事件分发
  1. dispatchTouchEvent 分发处理事件
  2. 如果view可用则调用mOnTouchListener(可消费调触摸事件)
  3. 在onTochEvent中处理事件
    3.1 如果view是disable且是cliable 则直接消费调事件
    3.2 如果是enable且discliable直接返回 不消费事件
    3.3 如果是enable且cliable则处理消费事件逻辑,如up事件就会触发clickListner

总结:view要消费调Down事件才会接受到后续事件,而事件达到view时可以被责任链里的ViewGroup拦截掉,一旦拦截掉后续的任何一个事件对View来说就不完整了,所以为了保证view可以获取所有事件,可以声明不让他们拦截自己的事件。自己也不要在onTouchListner里随便拦截会影响onTouchEvent的正常处理的。如果没有view处理就会向上继续传播处理

部分学习自老罗的博客

相关推荐