Android Framework原理

App启动过程

cbe7104d431624e6e21df450a2f4c9fafd4.jpg

  1. 点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求
  2. system_server进程接收到请求后,向zygote进程发送创建进程的请求
  3. Zygote进程fork出新的子进程,即App进程
  4. App进程,通过Binder IPC向sytem_server进程发起attachApplication请求
  5. system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求
  6. App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息
  7. 主线程在收到Message后,通过反射机制创建目标Activity,并回调Activity.onCreate()等方法
  8. App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染结束后便可以看到App的主界面

Android开机流程

1b6b5300b289d081da3f15b9a623f63e1a8.jpg

Android开机流程

BootLoader引导

当按开机键的时候,引导芯片开始从固化在ROM的预设代码开始执行,然后加载引导程序到RAM
BootLoader,又称为引导程序。它是在操作系统运行之前运行的一段程序
BootLoader负责初始化软件运行所需要的最小硬件环境,最后加载内核到内存

启动Kernel

这个入口的函数是start_kernel函数
start_kernel函数执行到最后调用了reset_init函数进行后续的初始化
start_kernel最终启动用户空间的init程序

启动Android

当初始化内核之后,init进程负责解析init.rc配置文件, 就会启动一个相当重要的祖先进程,也就是init进程,在Linux中所有的进程都是由init进程直接或间接fork出来的

* /system/bin/app_process_Zygote服务启动的进程名
* --start-system-server 表明Zygote启动完成后,需要启动System_Server进程
* socket zygote stream 666在Zygote启动时,创建一个权限为666的socket。此socket用来请求zygote创建新进程
* socket的fd保存在名称为"ANDROID_SOCKET_zygote"的环境变量中

init进程负责创建系统中最关键的几个核心daemon(守护)进程,尤其是zygote和System_Server进程

1. zygote进程 android启动的第一个Dalvik 虚拟机,它将负责启动Java世界的进程
2. zygote虚拟机启动子进程system_server,同时也可以看出zygote中定义了一个Socket,绑定666端口,用于接收ActivityManagerService启动应用程序的请求
3. System_Server进程  Binder通信的基础,它还提供了property service(属性服务),类似于windows系统的注册表服务
4. 系统里面重要的服务都是在这个进程里面开启的,例如AMS, WindowsManager, PackageManagerService等等都是由这个System_Server fork出来的
5. 在System_Server进程开启的时候,就会初始化ActivityManagerService 。同时,会加载本地系统的服务库,调用createSystemContext()创建系统上下文,创建ActivityThread及开启各种服务等等
6. system_server中开启了核心系统服务,并将系统服务添加到ServiceManager中,然后系统进入SystemReady状态

启动Home Activity

  1. 在systemReady状态,ActivityManagerService会与zygote的Socket通信,请求启动Home
  2. zygote收到AMS的连接请求后,执行runSelectLoopMode处理请求
  3. zygote处理请求会通过forkAndSpecialize启动新的应用进程,并最终启动Home
概况
1. 系统加电,执行bootloader。Bootloader负责初始化软件运行的最小硬件环境,最后加载内核到内存
2. 内核加载到内存后,进入内核引导阶段,在内核引导的最后,调用start_kernel进入内核启动阶段。start_kernel最终启动用户空间的init程序
3. init负责解析init.rc配置文件,开启系统守护进程。2个最重要的守护进程是zygote进程和serverManager进程。zygote是android启动的第一个Dalvik虚拟机,ServiceManager服务是Binder通信的基础
4. zygote虚拟机启动子进程system_server,在system_server中启动了核心系统服务,并将系统服务添加到ServiceManager中,然后系统进入SystemReady状态
5. 在SystemReady状态,ActivityManagerService与zygote中的socket通信,通过zygote启动home应用,进入系统界面

* 从步骤3开始, init启动后,上层的实现
1. init启动的核心Daemon服务包括Android的第一个Dalvik虚拟机Zygote
2. zygote定义一个socket,用于接受ActivityManangerService启动应用的请求
3. zygote通过fork系统调用创建system_server进程
4. 在system_server进程中,将会启动系统核心服务以及其他服务
5. 系统服务启动后会注册到ServiceManager中,用于Binder通信
6. ActivityManagerService进入systemReady状态
7. 在systemReady状态,ActivityManangerService会与zygote的Socket通信,请求启动Home
8. zygote收到AMS的连接请求后,执行runSelectLoopMode处理请求
9. zygote处理请求会通过forkAndSpecialize启动新的应用进程,并最终启动Home

Handler机制与底层实现原理

概念
Message - Message代表一个行为what或者一串动作Runnable, 每一个消息在加入消息队列时,都有明确的目标Handler
ThreadLocal - 线程本地存储区(Thread Local Storage,简称为TLS),每个线程都有自己的私有的本地存储区域,不同线程之间彼此不能访问对方的TLS区域。ThreadLocal的作用是提供线程内的局部变量TLS,这种变量在线程的生命周期内起作用,每一个线程有他自己所属的值(线程隔离)
MessageQueue (C层与Java层都有实现) - 以队列的形式对外提供插入和删除的工作, 其内部结构是以双向链表的形式存储消息的
Looper (C层与Java层都有实现) - Looper是循环的意思,它负责从消息队列中循环的取出消息然后把消息交给Handler处理
Handler - 消息的真正处理者, 具备获取消息、发送消息、处理消息、移除消息等功能

普通的线程是没有looper的,如果需要looper对象,那么必须要先调用Looper.prepare方法,而且一个线程只能有一个looper
Handler是如何完成跨线程通信的

* Android中采用的是Linux中的管道通信
* 关于管道,简单来说,管道就是一个文件
* 在管道的两端,分别是两个打开文件文件描述符,这两个打开文件描述符都是对应同一个文件,其中一个是用来读的,别一个是用来写的
* 消息队列创建时,会调用JNI函数,初始化NativeMessageQueue对象。NativeMessageQueue则会初始化Looper对象
* Looper的作用就是,当Java层的消息队列中没有消息时,就使Android应用程序主线程进入等待状态,而当Java层的消息队列中来了新的消息后,就唤醒Android应用程序的主线程来处理这个消息

整个消息机制流程

916c9a780fee654d666ee905b4f5c0fc4c7.jpg

Handler通过sendMessage()发送Message到MessageQueue队列
Looper通过loop(),不断提取出达到触发条件的Message,并将Message交给target来处理
经过dispatchMessage()后,交回给Handler的handleMessage()来进行相应地处理
将Message加入MessageQueue时,处往管道写入字符,可以会唤醒loop线程;如果MessageQueue中没有Message,并处于Idle状态,则会执行IdelHandler接口中的方法,往往用于做一些清理性地工作

ContentProvider原理

Android绘制原理

Activity的window组成,Activity内部有个Window成员,它的实例为PhoneWindow,PhoneWindow有个内部类是DecorView,这个DecorView就是存放布局文件的,里面有TitleActionBar和我们setContentView传入进去的layout布局文件

31ca6fcb6ec74d3b430808af6076064e4d7.jpg

  1. Window类时一个抽象类,提供绘制窗口的API
  2. PhoneWindow是继承Window的一个具体的类,该类内部包含了一个DecorView对象,该DectorView对象是所有应用窗口(Activity界面)的根View
  3. DecorView继承FrameLayout,里面id=content的就是我们传入的布局视图
  4. ContentView必须是一个ViewGroup
  5. ViewGroup 开始递归执行以下逻辑进行绘制
+ measure, 递归测量view的大小。有3种测量模式
    - MeasureSpec.EXACTLY表示确定大小
    - MeasureSpec.AT_MOST表示最大大小
    - MeasureSpec.UNSPECIFIED不确定
+ layout,递归布局view的位置
+ draw,递归绘制view
    - ViewRootImpl中的代码会创建一个Canvas对象,然后调用View的draw()方法来执行具体的绘制

AsyncTask源码分析

Binder机制及底层实现

进程空间分配

  1. 进程间,用户空间的数据不可共享,所以用户空间 = 不可共享空间
  2. 进程间,内核空间的数据可共享,所以内核空间 = 可共享空间
  3. 进程内用户与内核进行交互称为系统调用

Binder跨进程通信(IPC)的原理

88069b205828c640520df647876f046225b.jpg

  1. 先通过进程间的内核空间进行数据交互
  2. 再通过进程内的用户空间&内核空间进行数据交互,从而实现进程间的用户空间的数据交互
  3. 而Binder,就是充当连接两个进程(内核空间)的通道

使用步骤:
注册服务

* Server进程向Binder驱动发起服务注册请求
* Binder驱动将注册请求转发给ServiceManager进程
* ServiceManager进程添加该服务
* 此时ServiceManager进程拥有该服务信息

获取服务

* Client向Binder驱动发起获取服务的请求,传递要获取的服务名称(service name)
* Binder驱动将该请求转发给ServiceManager进程
* ServiceManager查找到Client需要的Server对应的服务信息
* 通过Binder驱动将上述服务信息返回给Client进程
* 此时client进程与server进程已经建立了连接

使用服务

* Client进程将参数数据发到Server进程
    1. client 进程将需要的传送的数据放到client进程的共享内存;(当前线程被挂起)
    2. Binder驱动从client的共享内存中读取数据,并根据ServiceManager进程里面的Server信息找到对应的Server进程
    3. Binder驱动将数据copy到Server进程的共享内存里,并通知Server进程解包
* Server进程根据Client进程要求,调用目标方法
    1. 接到Binder驱动通知后,Server进程从线程池中取出线程,进行数据解包和调用目标方法
    2. 将最终方法结果写到自己的共享内存
* Server进程将目标方法的结果,返回给Client进程
    1. Binder驱动程序将Server进程的共享内存里面的数据(方法执行结果) copy 到client进程的共享内存
    2. 通知client进程获得返回结果(此时client进程之前被挂起的线程被重新唤醒)

78dc9c2dc51ff2dd563a821ffb83ec1ec08.jpg

Client进程、Server进程 & Service Manager 进程之间的交互 都必须通过Binder驱动(使用 open 和 ioctl文件操作函数),而非直接交互
Client进程、Server进程 & Service Manager进程属于进程空间的用户空间,不可进行进程间交互
Binder驱动 属于 进程空间的 内核空间,可进行进程间 & 进程内交互

9d4c249b7d16b708ccd40c865d3cd0ef172.jpg

Binder驱动 & Service Manager进程 属于 Android基础架构(即系统已经实现好了);而Client 进程 和 Server 进程 属于Android应用层(需要开发者自己实现)

4190589cea674169ef9e3420bab1168ee20.jpg

ActivityThread工作原理

Window 、WMS的工作原理

ThreadLocal原理,实现及如何保证Local属性

每个Thread维护一个ThreadLocalMap映射表,这个映射表的key是ThreadLocal实例本身,value是真正需要存储的Object

Android线程有没有上限

android本身就是linux系统 所以查看命令和linux一样

Android内存限制

dalvik.vm.heapstartsize 表示 初始内存大小是8m
dalvik.vm.heapgrowthlimit 表示标准内存大小是96m 一般应用都是这么大
dalvik.vm.heapsize 表示 在manifest配置文件中application标签下配置 android:largeHeap="true"时的内存大小

Android apk大小限制

apk安装包大小理论上没有限制。但是各个应用商店为了有大小限制google play 要求小于50M , 扩展包可以扩展到2g
压测: 800M的apk是没问题的只是安装的时间比较长。1.6G的apk包则把手机弄死机

线程池有没有上限

ThreadPoolExecutor构造函数的maximumPoolSize决定

AndroidToast原理分析

Art和Dalvik对比

ART 的机制与 Dalvik 不同。在Dalvik下,应用每次运行的时候,字节码都需要通过即时编译器(just in time ,JIT)转换为机器码,这会拖慢应用的运行效率,而在ART 环境中,应用在第一次安装的时候,字节码就会预先编译成机器码,使其成为真正的本地应用。这个过程叫做预编译(AOT,Ahead-Of-Time)。这样的话,应用的启动(首次)和执行都会变得更加快速。

BlockCanaryEx原理

即整个应用的主线程,只有这一个looper,不管有多少handler,最后都会回到这里

public static void loop() {
    ...

    for (;;) {
        ...

        // This must be in a local variable, in case a UI event sets the logger
        Printer logging = me.mLogging;
        if (logging != null) {
            logging.println(">>>>> Dispatching to " + msg.target + " " +
                    msg.callback + ": " + msg.what);
        }

        msg.target.dispatchMessage(msg);

        if (logging != null) {
            logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
        }

        ...
    }
}

设置Printer对象,判断是否超过预期时间,notifyLog

Android GC探究

虚拟机原理,如何自己设计一个虚拟机(内存管理,类加载,双亲委派)

对于Activity 的 onCreate 等生命周期的函数为什么不会因为 Looper.loop()里的死循环卡死而永无机会执行

View 的绘制到底是怎样完成的,它又为什么不会因为 Looper.loop()里的死循环卡死而永无机会刷新

子线程真的不能刷新UI

 

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
前言 第一部分 准备篇 第1章 Android开发简介 1.1 Android基本概念 1.1.1 Android简介 1.1.2 Android的系统构架 1.1.3 Android应用程序框架 1.2 OMS介绍 1.2.1 OPhone介绍 1.2.2 Widget介绍 1.3 小结 第2章 Android开发环境搭建 2.1 Android开发准备工作 2.2 开发包及其工具的安装和 配置 2.2.1 安装JDK和配置Java开发 环境 2.2.2 Eclipse的安装与汉化 2.2.3 SDK和ADT的安装和 配置 2.3 创建第一个Android项目——HeUoAndroid 2.3.1 创建HelloAndroid项目 2.3.2 运行HelloAndroid及模拟器的使用 2.3.3 调试HelloAndroid 2.4 小结 第二部分 基础篇 第3章 Android程序设计基础 3.1 Android程序框架 3.1.1 Android项目目录结构 3.1.2 Android应用解析 3.2 Android的生命周期 3.3 Android程序U设计 3.4 小结 第4章 用户界面开发 4.1 用户界面开发详解 4.1.1 用户界面简介 4.1.2 事件处理 4.2 常用控件应用 4.2.1 文本框(Textiew) 4.2.2 列表(ListView) 4.2.3 提示(T0ast) 4.2.4 编辑框(EditText) 4.2.5 单项选择(RadioGroup、RadioButton 4.2.6 多项选择(CheckBox) 4.2.7 下拉列表(Spinner) 4.2.8 自动提示(AutoComplete.TextⅥew) 4.2.9 日期和时间(DatePicker、TimePicker) 4.2.10 按钮(Button) 4.2.1l 菜单(Menu) 4.2.12 对话框(Dialog) 4.2.13 图片视图(ImageView) 4.2.14 带图标的按钮(ImageButton) 4.2.15 拖动效果(Gallery) 4.2.16 切换图片(hmgeSwilcher) 4.2.17 网格视图(GridView) 4.2.18 卷轴视图(ScrollView) 4.2.19 进度条(ProgressBar) 4.2.20 拖动条(SeekBar) 4.2.21 状态栏提示(Notification、NotificationManager) 4.2.22 对话框中的进度条(ProgressDialog) 4.3 界面布局 4.3.1 垂直线性布局 4.3.2 水平线性布局 4.3.3.相对布局(RelativeLayout) 4.3.4 表单布局(TableLayout) 4.3.5 切换卡(TabWidget) 4,4 小结 第5章 Android游戏开发 5.1 Android游戏开发框架 5.1.1 View类开发框架 5.1.2 SurfaceView类开发框架 5.2 Graphics类开发 5.5.1 Paint和Color类介绍 5.2.2 Canvas类介绍 5.2.3 几何图形绘制 5.2.4 字符串绘制 5.2.5 图像绘制 5.2.6 图像旋转 5.2.7 图像缩放 5.2.8 图像像素操作 5.2.9 Shader类介绍 5.2.10 双缓冲技术 5.2.11 全屏显示 5.2.12 获得屏幕属性 5.3 动画实现 5.3.1 Tween动画 5.3.2 Frame动画 5.3.3 GIF动画播放 5.4 小结 第6章 Android数据存储 6.1 Android数据存储初探 6.2 数据存储之Shared Preferences 6.3 数据存储之Files 6.4 数据存储之Network 6.5 Android数据库编程 6.5.1 SQLite简介 6.5.2 SQLite编程详解 6.5.3 SQLiteOpenHelper应用 6.6 数据共享(ContentProviders) 6.7 小结 第7 章多媒体开发 7.1 多媒体开发详解 7.1.1 Open Core 7.1.2 MediaPlayer 7.1.3 MediaRecorder 7.2 播放音乐 7.3 播放视频 7.4 录制歌曲 7.5 相机设置 7.6 闹钟设置 7.7 铃声设置 7.8 小结 第8章 网络与通信 8.1 网络通信基础 8.1.1 无线网络技术 8.1.2 Android网络基础 8.2 HTTP通信 8.2.1 HttpURLConnection接口 8.2.2 HttpClient接口 8.2.3 实时更新 8.3 Socket通信 8.3.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

flybirding10011

谢谢支持啊999

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值