我们知道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. word/excel/ppt 2 PDF

    PHP 实现 word/excel/ppt 转换为 PDF 一般最常见的就是利用OpenOffice来转换,来看看实现的核心代码: class PDFConverter { private $com; ...

  2. PHP DES-ECB加密对接Java解密

    最近公司有个业务,需要对接第三方接口,但是参数是需要加密的,对方也只提供了一个java的demo,在网上到处搜索,没有找到直接就能用的方法,后来还是跟公司的Android工程师对接出来的,在这里记录一 ...

  3. 【Henu ACM Round#16 E】Paths and Trees

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 感觉很像一道最短路. 然后就试了一发. 结果真的是.. 只要用一个优先队列优化的dijkstra算法求出每个点的最短路上的前一个点是 ...

  4. POJ 3225 Help with Intervals(线段树)

    POJ 3225 Help with Intervals 题目链接 集合数字有的为1,没有为0,那么几种操作相应就是置为0或置为1或者翻转,这个随便推推就能够了,然后开闭区间的处理方式就是把区间扩大成 ...

  5. xcode 4 svn配置(host is unreachable)

    xcode 4 svn配置 先保证你的xcode中已经安装了command line tools xcode -> preferences -> downloads -> comma ...

  6. 一张图片让你了解android的事件分发机制

  7. POJ 1887 Testingthe CATCHER (LIS:最长下降子序列)

    POJ 1887Testingthe CATCHER (LIS:最长下降子序列) http://poj.org/problem?id=3903 题意: 给你一个长度为n (n<=200000) ...

  8. 线程池系列二:ThreadPoolExecutor讲解

    一.简介 1)线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, i ...

  9. POJ 1966 求无向图点连通度

    思路: n^2枚举(必须要n^2枚举啊)+拆点 特此嘲讽网上诸多垃圾题解,你们许多都是错的 -yyh //By SiriusRen #include <queue> #include &l ...

  10. UDP广播

    客户端UDP发送消息至服务器端服务器IP:192.168.1.114服务器端口:2014 客户端 Socket socket = new Socket(AddressFamily.InterNetwo ...