Android系统流程

Zygote的启动过程

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

Android应用程序安装过程

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

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

/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将计算型的逻辑单独放在一个进程内执行提升用户体验。socket

start流程ide

  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处理就会向上继续传播处理spa

部分学习自老罗的博客

相关文章
相关标签/搜索