Android应用运行过程(转)
首先,ActivityThread从main()函数开始执行,调用prepareMainLooper()为UI线程创建一个消息队列(MessageQueue)。

然后创建一个ActivityThread对象,在ActivityThread的初始化代码中会创建一个H(Handler)对象和一个ApplicationThread(Binder)对象。其中Binder负责接收远程AmS的IPC调用,接收到调用后,则通过Handler把消息发送到消息队列中,UI主线程会异步的从消息队列中取出消息并执行相应的操作,比如start stop pause等。
接着UI主线程调用Looper.loop()方法进入消息循环体,进入后就会不断的从消息队列中读取并处理消息。
当ActivityThread接收到AmS发送start某个Activity后,就会创建指定的Activity对象,Activity又会创建PhoneWindow类——>DecorView类——>创建相应的View或者ViewGroup。创建完成后,Activity需要把创建好的界面显示到屏幕上,于是调用WindowManager类,后者于是创建一个ViewRoot对象,该对象实际上创建了ViewRoot类和W类,创建ViewRoot对象以后,WindowManager再调用WmS提供的远程调用接口完成添加一个窗口并显示到屏幕上。
继续往下看,attach方法会通过代码mWindow = PolicyManager.makeNewWindow(this)实例化一个phoneWindow对象
PolicyManager的作用可参看博主的
然后接下来就是在activity开始onCreate调用时,会调用PhoneWIndow的setContentView方法, 当然这里有是否第一次的判断,然后调用方法installDecor(), 再调用generateDecor() 创建顶层视图 DecorView mDecor,DecorView是FrameLayout的子类;在方法generateLayout(mDecor) 中 会干些什么事儿呢?
该方法会做如下事情:(不想写了,在qinjuning的blog中copy了一下,谅解呀)
1、根据窗口的风格修饰类型为该窗口选择不同的窗口布局文件(根视图)。这些窗口修饰布局文件指定一个用来存放
Activity自定义布局文件的ViewGroup视图,一般为FrameLayout 其id 为: android:id="@android:id/content"。
例如窗口修饰类型包括FullScreen(全屏)、NoTitleBar(不含标题栏)等。选定窗口修饰类型有两种:
①、指定requestFeature()指定窗口修饰符,PhoneWindow对象调用getLocalFeature()方法获取值;
②、为我们的Activity配置相应属性,即android:theme=“”,PhoneWindow对象调用getWindowStyle()方法
获取值。
举例如下,隐藏标题栏有如下方法:requestWindowFeature(Window.FEATURE_NO_TITLE);
或者 为Activity配置xml属性:android:theme=”@android:style/Theme.NoTitleBar”。
PS:因此,在Activity中必须在setContentView之前调用requestFeature()方法。
确定好窗口风格之后,选定该风格对应的布局文件,这些布局文件位于 frameworks/base/core/res/layout/ ,
典型的窗口布局文件有:
R.layout.dialog_titile_icons R.layout.screen_title_icons
R.layout.screen_progress R.layout.dialog_custom_title
R.layout.dialog_title
R.layout.screen_title // 最常用的Activity窗口修饰布局文件
R.layout.screen_simple //全屏的Activity窗口布局文件
到最后了,ActivityManagerService准备resume一个Activity时,会回调该Activity的handleResumeActivity()方法,再调用Activity的makeVisible方法 ,显示创建的DectorView
下面是一些总结信息:
windowManager只是提供接口,用了桥接模式,真正实现是WindowManagerImpl类。而调用addiew方法的对象来自另一个类LocalWindowManager,它会做一些简单检查,再通过WindowManagerImp类的addview完成窗口添加。addview大概分三步执行:
1.校验该窗口是否已经添加过了。
2.判断窗口类型如果是子窗口,则找到它附属的父窗口
3.new一个ViewRootImpl对象,最后调用该对象的setView方法。
setView 方法会最终会通过ipc调用IwindowSession的add方法。Session类实现了该方法,并最终给WindowManagerService处理。客户端的工作至此就完成了。
这里说明一下ViewRootImpl类,这其实是个handler。自然的,它一部分功能就是对消息进行处理,将用户的一些操作分发到view中。它也是view和WindowManagerService的桥梁。可以看到它通过一个会话将信息传递到了WindowManagerService。而WIndowManagerService也会通过IWindow接口将指令通过消息的方式发送到ViewRootImpl,ViewRootImpl处理这些消息。
二.服务端
WindowManagerService的addWindow方法主要做三部分的处理。
1.做一些合法性校验
2.完成窗口数据的构建
3.完成窗口创建后需要作出的一些调整
我们只看第二部分。首先会new一个WindowState类,该类表示一个窗口。结合WindowToken和AppWindowToken,完整的定义了一个窗口内容。接着创建一个管道,用于处理消息输入。再然后调用attach方法,创建和Surface相关的内容,用于和surfaceFlinger交互。这样,整个窗口就搭建完成了。有了WindowState类对窗口属性的保存以及token对窗口归属的标识,之后就可以通过SurfaceFlinger绘制在屏幕上了。之后通过InputManager,也能处理消息和WindowManagerService之间的传递。保证窗口显示内容和用户操作保持一致性。
当然,WindowManagerService靠近10000行的代码完成了很多功能,因为这篇文章只会了解窗口管理的整个架构,这里不一一详解,以后有时间可能会把一些比较有意思的内容再看下:
1. 窗口的创建和删除
2. 窗口的显示和隐藏控制
3. Z-order顺序管理
4. 焦点窗口管理
5. 输入法窗口管理和墙纸窗口管理
6. 切换动画
7. 系统消息收集和分发、
接下来,用户开始在程序界面上操作,KeyQ线程不多把用户消息存储到QueueEvent队列中,InputDispatcherThread线程逐个取出消息,然后调用WmS中的相关函数处理该消息,当WmS发现该消息属于客户端某个窗口时,就会调用相应的窗口W接口。
W类是一个Binder,负责接收WmS的IPC调用,并把调用消息传递给ViewRoot,ViewRoot再把消息传递给UI主线程ActivityThread,ActivityThread解析该消息并作相应的处理,在客户端程序中,首先处理消息的是DecorView,如果DecorView不想处理该消息,则可以把该消息传递给其内部包含的子View或者ViewGroup,如果还没有处理,则传递给PhoneWindow,最后在传递给Activity。
一个应用中有哪些线程?
首先,我们都知道的UI线程即用户交互线程,用来处理用户消息和界面绘制;
其次,每个Binder对象对应一个线程;在ActivityThread中会创建ApplicationThread,他们都是继承Binder,这里会启动两个线程;
所以最少应该是3个线程.....然后开发人员自定义的子线程.....待续。
Android应用运行过程(转)的更多相关文章
- android的编译和运行过程深入分析
android的编译和运行过程深入分析 作者: 字体:[增加 减小] 类型:转载 首先来看一下使用Java语言编写的Android应用程序从源码到安装包的整个过程,此过程对了解android的编译和运 ...
- 编译可在Android上运行的qemu user mode
前言 本文在Ubuntu 64位系统上对qemu项目进行交叉编译,并且只编译与qemu user mode有关的代码. 下文中的”NDK”若无特殊说明均指”Android NDK”. 下文中”$NDK ...
- 系列篇|编译可在Android上运行的依赖库(一):glib库
前言 这是系列文章,它们由<编译可在Android上运行的glib库>及其他4篇文章组成,这4篇文章在“编译依赖库”一节中列出.由于glib库依赖于其他第三方库,所以需要先将依赖的第三方库 ...
- Cordova 打包 Android release app 过程详解
Cordova 打包 Android release app 过程详解 时间 -- :: SegmentFault 原文 https://segmentfault.com/a/119000000517 ...
- Android ART运行时与Dalvik虚拟机
这几天在做一个项目时需要在Android中使用OSGi框架(Apache Felix),于是在一个android 4.4.2 版本系统的某品牌的平板上实验. 实验内容很简单:把felix包里的feli ...
- Android ListView滑动过程中图片显示重复错乱闪烁问题解决
最新内容建议直接访问原文:Android ListView滑动过程中图片显示重复错乱闪烁问题解决 主要分析Android ListView滚动过程中图片显示重复.错乱.闪烁的原因及解决方法,顺带提及L ...
- Android的init过程(二):初始化语言(init.rc)解析
Android的init过程(一) 本文使用的软件版本 Android:4.2.2 Linux内核:3.1.10 在上一篇文章中介绍了init的初始化第一阶段,也就是处理各种属性.在本文将会详细分析i ...
- Android的init过程(二):初始化语言(init.rc)解析【转】
转自:http://www.cnblogs.com/nokiaguy/p/3164799.html Android的init过程(一) 本文使用的软件版本 Android:4.2.2 Linux内核: ...
- android开机启动过程
Android系统开机主要经历三个阶段: bootloader启动 Linux启动 Android启动 启动文件: 对于机器从通电到加载Linux系统一般需要三个文件:bootloader(引导文件) ...
随机推荐
- public <T> void method(T var)
今天项目中遇到这样一个方法: public <T> void method(T var) 不太明白什么意思,后来搜索下几篇文章,自己总结一下,和大家分享. 先看例子: 1.static v ...
- 2015年4月29日 dayofweek
#include <stdio.h>#include <stdlib.h>int DayofYear(int year, int month, int day);#define ...
- cocos2d-x 3.x 触摸事件
HelloWorldScene.h bool touchBegan(cocos2d::Touch*touch, cocos2d::Event*event);//触摸开始,返回bool类型 void t ...
- Linux 监控文件事件
某些应用程序需要对文件或者目录进行监控,来侦测其是否发生了某些事件.Linux很贴心的为我们提供了inotify API,也是Linux的专有. inotify API 在使用之前一定要有一个inot ...
- Html基础详解之(jquery)
jquery选择器: #id 根据给定的ID匹配一个元素,如果选择器中包含特殊字符,可以用两个斜杠转义.(注:查找 ID 为"myDiv"的元素.) <!DOCTYPE ht ...
- zf-关于调用页面提示找不到className的原因
多亏了蒋杰 还好他上次告诉我 关于节点的问题 我一看到这个函数就想到了他以前教我的 我这里一开始就调用js函数了 所以没获取到节点 后来把方法换到这里就OK了
- zf-关于<ww:iterator /> 标签中的<td /> 标签添加序号问题
一开始代码是这样的 那个<ww:if> 标签 是我添加的,可是添加之后出问题了. 因为我加了一个判断语句,使得不需要的信息没显示出来,导致#li.count 这个显示下标的方法行不通了 之 ...
- PHP 命名空间以及自动加载(自动调用的函数,来include文件)
这篇文章的目的是记录 1. php中的自动加载函数 __autoload(), 和 spl_autoload_register()函数, 2 .php中命名空间的使用. 一.当不使用命名空间的时候 a ...
- Blocks(闭包)
转自:http://my.oschina.net/joanfen/blog/317644?fromerr=ATWzC3Y2 Block 与传统代码相比较更加轻量,调用简洁方便,而且可以返回多个参数,使 ...
- Java关键字transient和volatile小结(转)
Java关键字transient和volatile小结(转) transient和volatile两个关键字一个用于对象序列化,一个用于线程同步,都是Java中比较高阶的话题,简单总结一下. tran ...