我们知道Android是以一个Activity为单位的,可是我们并没有看到一个Activity是怎么開始启动的。

今天我 们就从Android的源码開始讲吧。

ActivityThread:

Android的一个apk在打开时,使用到的第一个类就是这个类。我们先来说这个类。等说完这个类就能了解Android应用程序的启动原理了。

这货名字取名有一个Thread结尾。貌似是一个线程类。事实上他并非一个线程类,这个类没有继承不论什么类。或者说是直接继承在Object类。我们来看ActivityThread源码:

public final class ActivityThread {
....
}

这是ActivityThread定义时候的的源码。能够看出他根本没有继承不论什么类。那他为什么要以Thread来结尾的。貌似非常不合理。

事实上不然。

想必大家应该Android的异步线程机制吧。事实上ActivityThread在创建的时候同一时候也启动了一个线程,这个线程就是一个异步线程。他创建出了MessageQueue,并同一时候进行消息的轮询,因此当这个应用程序在执行时。这个线程是一直都在的。这个线程就是应用程序的主线程,UI的处理等都是在这个线程处理的。

在AcitivityThread这个类的是有一个main方法的。我们知道java应用程序的入口就是main方法。这就是程序的入口。

我们来看ActivityThread的源码:

    public static void main(String[] args) {
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
Security.addProvider(new AndroidKeyStoreProvider());
Process.setArgV0("<pre-initialized>");
//关键部分,看这里
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}

其它的部分我们先不要管,先看关键部分。就是我凝视的那个地方。

在这里先是使用Looper.prepareMainLooper();方法来创建一个MessageQueue实例。

prepareMainLooper内部会调用prepare()方法创建消息队列(MessageQueue)。创建出来之后,就会创建一个ActivityThread对象。这个ActivityThread对象内部会创建出一个Handler和一个ApplicationThread对象,当中这两个对象稍后会介绍,(这里应该有一个中断向量,或者然后再启一个线程去解说Handler对象和Application对象,哈哈)先压一压。在创建出这个ActivityThread对象之后。中间部分略过不表。之后这里会调用Looper.loop(),是消息队里进行循环。所以说这个ActivityThread是一直都在的,由于须要一直等待取其它线程发过来的消息。

这个线程就是我们的主线程。

Activity。Service等的管理都是在这里。之后会介绍。

好了。这个过程想必大家都了解了。如今我们说一说我们的Handler和ApplicationThread。

在ActivityThread中的这个Handler事实上是一个内部类。类名是H,对,就是H一个字母。他是继承自Handler对象的。我们来看一下源码:



在第3行,在这里我们能够看到。他创建了一个H类的实例。注意,这里是类的成员变量区域,不是在某个方法里面。意思就是这个类在创建的同一时候。这个mH对象就创建出来了。所以说这个mH相当于是主线程的,也就是在main里创建出来的。而这个对象是用于其它线程想主线程发消息的。

我们再来看看main函数中我们没有提到的那部分:

      Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
AsyncTa

我们在if语句里面能够看到这样一个语句sMainThreadHandler = thread.getHandler();thread是刚刚创建出来的ActivityThread实例,而getHandler方法返回的正是mH实例。

接下来说一下ApplicationThread这个类,该类是ActivityThread的内部类。该类的作用是什么呢。事实上这里涉及到了进程间的通信,这个类是负责接收远程的AmS(ActivitymanagerService)IPC(进程间通信)调用的。而这个的调用通常是Android系统去调用的。这个相当于一种进程间通信,Android系统会有一个服务。用于监控用户的操作等,当用户进行相关操作是会通过进程之间的通信去通知这个应用程序做对应的反应。比方启动一个Activity。当这个类收到通知之后。接下来就会安排Activity的启动,我们能够看一下这个类的源码:



这里贴出当中的部分代码,注意不是这个类的所有代码,仅仅是当中的一部分。我们看一下当中的第二个方法

schedulePauseActivity该方法的意思应该是“安排暂停activity”,该方法就是让Activity调用onPause的代码。以下的其它代码也都是相似的。

都是管理service和activity的代码。在这些方法的内部都会调用sendMessage,而这种方法的内部又会继续调用mh.sendMessage()。将暂停或者启动Activity的相关消息安排到主线程的MessageQueue队列中,等待消息队列轮询来处理该消息。我们能够从这些方法的名字也能看出来,schedule是安排的意思。“安排暂停activity”就表示你把“暂停activity”这件事安排一下,等MessageQueue手头的事忙完,再来处理“暂停activity”的事。而安排这件事的人是谁呢,就是mH这个助理了,由他把消息发送给MessageQueue。

Android启动原理剖析的更多相关文章

  1. MySQL 启动原理剖析

    200 ? "200px" : this.width)!important;} --> 介绍 本篇文章主要从查看MySQL的启动命令的代码来详细了解MySQL的启动过程,内容 ...

  2. 64、Spark Streaming:StreamingContext初始化与Receiver启动原理剖析与源码分析

    一.StreamingContext源码分析 ###入口 org.apache.spark.streaming/StreamingContext.scala /** * 在创建和完成StreamCon ...

  3. 写给 Android 应用工程师的 Binder 原理剖析

    写给 Android 应用工程师的 Binder 原理剖析 一. 前言 这篇文章我酝酿了很久,参考了很多资料,读了很多源码,却依旧不敢下笔.生怕自己理解上还有偏差,对大家造成误解,贻笑大方.又怕自己理 ...

  4. NFC(6)NFC编程的几个重要类,NFC硬件启动android应用原理

    用于NFC编程的几个重要类 Tag NFC 标签 NfcAdapter Nfc 的适配类 NdefMessage 描述NDEF格式的信息 NdefRecord 描述NDEF信息的一个信息段,类似tab ...

  5. Android启动篇 — init原理(二)

    ========================================================          ================================== ...

  6. Android启动篇 — init原理(一)

    ========================================================          ================================== ...

  7. 原理剖析-Netty之服务端启动工作原理分析(下)

    一.大致介绍 1.由于篇幅过长难以发布,所以本章节接着上一节来的,上一章节为[原理剖析(第 010 篇)Netty之服务端启动工作原理分析(上)]: 2.那么本章节就继续分析Netty的服务端启动,分 ...

  8. ARouter原理剖析及手动实现

    ARouter原理剖析及手动实现 前言 路由跳转在项目中用了一段时间了,最近对Android中的ARouter路由原理也是研究了一番,于是就给大家分享一下自己的心得体会,并教大家如何实现一款简易的路由 ...

  9. ASP.NET Core 运行原理剖析1:初始化WebApp模版并运行

    ASP.NET Core 运行原理剖析1:初始化WebApp模版并运行 核心框架 ASP.NET Core APP 创建与运行 总结 之前两篇文章简析.NET Core 以及与 .NET Framew ...

随机推荐

  1. Jupyter Notebook 常用的快捷键

    Jupyter Notebook 有两种键盘输入模式.编辑模式,允许你往单元中键入代码或文本:这时的单元框线是绿色的.命令模式,键盘输入运行程序命令:这时的单元框线是灰色. Shift+Enter : ...

  2. [HNOI2006]超级英雄(二分+网络流)

    [HNOI2006]超级英雄 题目描述 现在电视台有一种节目叫做超级英雄,大概的流程就是每位选手到台上回答主持人的几个问题,然后根据回答问题的多少获得不同数目的奖品或奖金.主持人问题准备了若干道题目, ...

  3. [SDOI2011]消防(树的直径)

    [SDOI2011]消防 题目描述 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000). 这个国家的人对火焰有超越宇宙的热情, ...

  4. 洛谷 P2104 二进制

    P2104 二进制 题目描述 小Z最近学会了二进制数,他觉得太小的二进制数太没意思,于是他想对一个巨大二进制数做以下 4 种基础运算: 运算 1:将整个二进制数加 1 运算 2:将整个二进制数减 1 ...

  5. easyui combobox keyhandler使用

    easyui combobox keyhandler使用 在combo组件中有属性:   keyHandler : { up : function() { console.log('upupup'); ...

  6. 第6章8节《MonkeyRunner源代码剖析》Monkey原理分析-事件源-事件源概览-小结

    本章我们重点环绕处理网络过来的命令的MonkeySourceNetwork这个事件源来阐述学习Monkey是怎样处理MonkeyRunner过来的命令的.以下总结下MonkeyRunner从启动Mon ...

  7. Android带索引联系人列表

    网上Android联系人列表的样例也非常多,都和微信的联系人差点儿相同,因为项目用到了联系人列表索引功能(产品把字母item给去掉了),只是也还是好实现.这里我也来分享分享我的实现,免得以后忘了.那先 ...

  8. Hive的单节点集群详细启动步骤

    说在前面的话, 在这里,推荐大家,一定要先去看这篇博客,如下 再谈hive-1.0.0与hive-1.2.1到JDBC编程忽略细节问题 Hadoop Hive概念学习系列之hive三种方式区别和搭建. ...

  9. LINUX上使用GDB单步调试Chromium Android C++代码。

    ###动机###在LINUX使用GDB单步调试Chromium Android C++代码. [1]编译android平台Chromium, 修改GN文件中编译选项:-g -O0 使得编译优化更少,便 ...

  10. ThinkPad X260 UEFI安装 win7 64位 方法

    ThinkPad X260   UEFI安装 win7 64位 方法 1.使用DG重新格式化硬盘,格式为GPT 2.使用CGI  安装 WIM文件 (image不知是否可以,下次测试) 3.改BIOS ...