我们知道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. mpstat---用于多CPU环境下,显示各个可用CPU的状态

    mpstat命令指令主要用于多CPU环境下,它显示各个可用CPU的状态系你想.这些信息存放在/proc/stat文件中.在多CPUs系统里,其不但能查看所有CPU的平均状况信息,而且能够查看特定CPU ...

  2. [TJOI2017]城市(树的直径)

    [TJOI2017]城市 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速公路相互可达, ...

  3. main()函数的形参

    main函数中的第一个参数argc代表的是向main函数传递的参数个数,第二个参数argv数组代表执行的程序名称和执行程序时输入的参数 #include <stdio.h> int mai ...

  4. 洛谷 P2695 骑士的工作

    P2695 骑士的工作 题目背景 你作为一个村的村长,保卫村庄是理所当然的了.今天,村庄里来了一只恶龙,他有n个头,恶龙到处杀人放火.你着急了.不过天无绝人之路,现在来了一个骑士团.里面有m位成员(往 ...

  5. ArcGIS api for javascript——放大时切换图层

    描述 本例展示了如何在地图里指出显示的缓存或切片的细节等级(LODs).当打开示例地图,可以看到一些来自ArcGIS Online ESRI_Imagery_World_2D图层的影像.这个应用程序配 ...

  6. 【 D3.js 入门系列 --- 2.1 】 关于怎样选择,插入,删除元素

    本人的个人博客首页为: http://www.ourd3js.com/  ,csdn博客首页为:http://blog.csdn.net/lzhlzz/. 转载请注明出处,谢谢. 在D3.js中,选择 ...

  7. 做一个萌萌哒的button之box-shadow

    接上篇:http://blog.csdn.net/u010037043/article/details/47035077 一.box-shadow box-shadow是给元素块加入周边阴影效果. b ...

  8. [Recompose] Configure Recompose to Build React Components from RxJS Streams

    Recompose provides helper functions to stream props using an Observable library of your choice into ...

  9. Shell脚本中替换字符串等操作

    在做shell批处理程序时候,常常会涉及到字符串相关操作. 有非常多命令语句.如:awk,sed都能够做字符串各种操作. 事实上shell内置一系列操作符号.能够达到类似效果,大家知道,使用内部操作符 ...

  10. 维护的JSP站点数据丢失

    两个月前换了份工作,然后接手了三台server.上面乱七八糟的网站和应用大把. 当中有维护一个瀚石苑:http://www.hanshiyuan.com/.三天两头的丢失数据. 都不知道怎么找回,好在 ...