我们知道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. CMSIS-RTOS 时间管理之虚拟定时器Virtual Timers

    虚拟定时器Virtual Timers CMSIS-RTOS API里有几个向下计数的虚拟定时器,它们实现计数完成时用户的回调功能.每个定时器都可以配置成单次计数或重复计数模式,它们可以在定义定时器结 ...

  2. [Python] Histograms for analysis Daily return

    A histogram is an accurate representation of the distribution of numerical data. Y axis is the occur ...

  3. java 究竟老年代和年轻代的比例为多大合适呢?

    眼下我还没有这方面过多的经验,和切身体会 只是以我眼下的水平看来,年轻代不宜大,假设年轻代大会导致转为老年代的时候,老年代撑不下.导致full gc.回收停顿时间过长

  4. PCL ubuntu-12.04

    1.apt-get install build-essential cmake cmake-qt-gui 2.sudo add-apt-repository ppa:v-launchpad-joche ...

  5. strchr函数的实现而不是使用

    刚刚在写一个程序的时候突然须要用到定位到一个字符串中第一次出现某个字符的位置,于是就找到了strchr()函数,之前从没实用过的,^_^当然我能够直接调用就可以.可是拥有良好程序素质的洗衣袋决定要想实 ...

  6. BootstrapDialog模态框

    5最近是比较烦直接使用Bootstrap里面的模态框,满屏都是模态框代码,看得心烦.然后想起以前使用的BootstrapDialog.show()的方式,挺简单好用的.然后就拿出来分享一下. 1.下载 ...

  7. POJ 3622 multiset

    思路: 放一个链接 是我太懒了 http://blog.csdn.net/mars_ch/article/details/52835978 嗯她教的我(姑且算是吧) (一通乱搞就出来了-) //By ...

  8. POJ - 3847 Moving to Nuremberg 动归

    POJ - 3847 Moving to Nuremberg 题意:一张无向有权图,包括边权和点权,求一点,使得到其他点的点权*边权之和最小 思路: #pragma comment(linker, & ...

  9. matlab中plot画图参数的设置

    原文链接:http://blog.sciencenet.cn/blog-281551-573856.html 一.Matlab绘图中用到的直线属性包括: (1)LineStyle:线形 (2)Line ...

  10. Vuejs2.0构建一个彩票查询WebAPP(1)

    说明:本人也是刚接触VUE.js,作为一个学习笔记,旨在与初学者共同学习.其中编程语法错误或者写作水平刺眼,还望轻喷. 使用工具:Visual Studio Code.技术栈为vue2+vuex+ax ...