一  Android采用分层的架构,分为四层,从高层到底层分为

应用程序层(app+System apps)                                             
应用程序框架层(Java API Framework)                                   ↑
系统运行库和运行环境层(Libraries + android Runtime)            ↑ 
Linux核心层(HAL+ Linux Kernel)                                             
images
images

1. Linux核心层

linux内核(Linux Kernel)

Android平台的基础,直接和硬件打交道。硬件驱动、进程管理、内存管理、网络管理的功能在这里实现。

硬件抽象层(Hardware Abstraction Layer)

为上层的Java API Framework提供相关硬件的界面显示,Audio,Bluetooth等是组成硬件抽象层的库模块,实现每个硬件的界面显示功能。

2. 系统运行库和运行环境层

Android 运行环境(Android Runtime)

Android 5.0(API 21)之前使用的是Dalvik虚拟机,之后被ART所取代。
ART是Android操作系统的运行环境,通过运行虚拟机来执行dex文件。其中,dex文件是专为安卓设计的的字节码格式,好处多多,不再赘述。Android toolchain(一种编译工具)可以将Java代码编译为dex字节码格式,过程如下图,jack是一种编译工具链(tool chain)

images

原生C/C++ 库(Native c/c++ Libraries)

上面提到的ART就依赖于C/C++库。开发者可以通过调用Java API Framework来使用原生库的功能,也可以用Android NDK直接调用原生库。

 

3. 应用程序框架层

java API Framework

我们最常用的组件和服务都在这一层,也是每一个安卓开发者必须要熟悉的一层

4. Application层

系统应用(system apps)

可以理解为内置在Android系统的app,我们可以像调用Java API Framework层一样直接调用系统app。

 

二  Android四大组件

android四大组件分别是:Activity, service,content provider,broadcast receiver

1. Activity

前台界面, 直接面向User, 提供UI和操作.

android 中,Activity 相当于一个页面,可以在Activity中添加Button、CheckBox 等控件,一个android 程序有多个Activity组成。

activity有四种状态:

Runing :一个新 Activity 启动入栈后,它在屏幕最前端,处于栈的最顶端,此时它处于可见并可和用户交互的激活状态。

Paused :当 Activity 被另一个透明或者 Dialog 样式的 Activity 覆盖时的状态。此时它依然与窗口管理器保持连接,系统继续维护其内部状态,所以它仍然可见,但它已经失去了焦点故不可与用户交互。

Stoped :当 Activity 被另外一个 Activity 覆盖、失去焦点并不可见时处于 Stoped 状态。

Killed :Activity 被系统杀死回收或者没有被启动时处于 Killed 状态。

 

2. Service

后台任务.

一个Service 是一段长生命周期的,没有用户界面的程序,可以用来开发如监控类程序。

比较好的一个例子就是一个正在从播放列表中播放歌曲的媒体播放器。在一个媒体播放器的应用中,应该会有多个activity,让使用者可以选择歌曲并播放歌曲。然而,音乐重放这个功能并没有对应的activity,因为使用者当然会认为在导航到其它屏幕时音乐应该还在播放的。在这个例子中,媒体播放器这个activity 会使用Context.startService()来启动一个service,从而可以在后台保持音乐的播放。同时,系统也将保持这个service 一直执行,直到这个service 运行结束。另外,我们还可以通过使用Context.bindService()方法,连接到一个service 上(如果这个service 还没有运行将启动它)。当连接到一个service 之后,我们还可以service 提供的接口与它进行通讯。拿媒体播放器这个例子来说,我们还可以进行暂停、重播等操作。

3. Content Provider 内容提供器

数据提供者.

主要的作用就是将程序的内部的数据和外部进行共享,为数据提供外部访问接口,被访问的数据主要以数据库的形式存在,而且还可以选择共享哪一部分的数据。这样一来,对于程序当中的隐私数据可以不共享,从而更加安全。contentprovider是android中一种跨程序共享数据的重要组件。

4. Broadcast Receiver

广播接收者.

广播被分为两种不同的类型:“普通广播(Normal broadcasts)”和“有序广播(Ordered broadcasts)”。普通广播是完全异步的,可以在同一时刻(逻辑上)被所有接收者接收到,消息传递的效率比较高,但缺点是:接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播;然而有序广播是按照接收者声明的优先级别(声明在intent-filter元素的android:priority属性中,数越大优先级别越高,取值范围:-1000到1000。也可以调用IntentFilter对象的setPriority()进行设置),被接收者依次接收广播。如:A的级别高于B,B的级别高于C,那么,广播先传给A,再传给B,最后传给C。A得到广播后,可以往广播里存入数据,当广播传给B时,B可以从广播中得到A存入的数据。
android 广播分为两个角色:广播发送者、广播接收者

三  Android命名规范

1 包名

采用反域名命名规则,全部使用小写字母。一级包名为com二级包名为xx(可以是公司或则个人的随便)三级包名根据应用进行命名四级包名为模块名或层级名

例如:com.公司名称简写.项目名称简写.模块名

2 类名

采用大驼峰命名法,尽量避免缩写,除非该缩写是众所周知的

例如:LoginActivity

3  接口

命名规则与类一样采用大驼峰命名法,多以able或ible结尾

例如:interface Runna ble;interface Accessible。

4  方法

动词或动名词,采用小驼峰命名法

例如:onCreate(),run()

5  变量

采用小驼峰命名法。类中控件名称必须与xml布局id保持一致

用统一的量词通过在结尾处放置一个量词,就可创建更加统一的变量,它们更容易理解,也更容易搜索。例如,请使用strCustomerFirst和strCustomerLast,而不要使用strFirstCustomer和strLastCustomer。

6  常量

全部大写,采用下划线命名法

例如:MIN_WIDTH,MAX_HEIGHT

 

四 安卓方法

1 onCreate()

onCreate函数是在activity初始化时调用,在onCreate()中调用setContentView(int)函数填充屏幕的UI,一般通过findViewById(int)返回xml中定义的视图或组件的ID。子类在重写onCreate()方法的时候必须调用父类的onCreate()方法,即super.onCreate(),否则会抛出异常。

一个activity启动调用的第一个函数就是onCreate,它主要做这个activity启动时一些必要的初始化工作,这个函数调用完后,这个activity并不是说就已经启动了,或者是跳到前台了。而是还需要其他的大量工作,

我们知道:onCreate之后还有onRestart()和onStart()等,实际上onStart()调用完毕了这个activity还没有完全启动,也只是前台可见,直到 onResume() 调用后这个onCreate才算终于启动。

2 onStart()

在 onCreate() 方法之后被调用,或者在 Activity 从 Stop 状态转换为 Active 状态时被调用,一般执行了onStart()后就执行onResume()。

 

3 onResume()

在 Activity 从 Pause 状态转换到 Active 状态时被调用。

 

五 安卓启动流程

  • bootloader启动内核和init进程.
  • init进程分裂出更多名为”daemons(守护进程)”的底层的Linux进程, 诸如android debug deamon, USB deamon等. 这些守护进程处理底层硬件相关的接口.
  • init进程会启动一个非常有意思的进程—“Zygote”. 顾名思义, 这是一个Android平台的非常基础的进程. 这个进程初始化了第一个VM, 并且预加载了framework和众多App所需要的通用资源.
  • 开启一个Socket接口来监听请求, 根据请求孵化出新的VM来管理新的App进程. 
  • 一旦收到新的请求, Zygote会基于自身预先加载的VM来孵化出一个新的VM创建一个新的进程.
  • 启动Zygote之后, init进程会启动runtime进程.
  • Zygote会孵化出一个超级管理进程—System Server.
  • SystemServer会启动所有系统核心服务, 例如Activity Manager Service, 硬件相关的Service等.
  • 到此, 系统准备好启动它的第一个App进程—Home进程了.

六 APP启动流程

用户点击Home上的一个App图标, 启动一个应用时:

 

Click事件会调用startActivity(Intent), 会通过Binder IPC机制, 最终调用到ActivityManagerService.

该Service会执行如下操作:

  • 第一步通过PackageManager的resolveIntent()收集这个intent对象的指向信息.
  • 指向信息被存储在一个intent对象中.
  • 下面重要的一步是通过grantUriPermissionLocked()方法来验证用户是否有足够的权限去调用该intent对象指向的Activity.
  • 如果有权限, ActivityManagerService会检查并在新的task中启动目标activity.
  • 现在, 是时候检查这个进程的ProcessRecord是否存在了.

如果ProcessRecord是null, ActivityManagerService会创建新的进程来实例化目标activity.

6.1 创建进程

ActivityManagerService调用startProcessLocked()方法来创建新的进程, 该方法会通过前面讲到的socket通道传递参数给Zygote进程. Zygote孵化自身, 并调用ZygoteInit.main()方法来实例化ActivityThread对象并最终返回新进程的pid.

ActivityThread随后依次调用Looper.prepareLoop()和Looper.loop()来开启消息循环.

流程图如下:

6.2 绑定Application

接下来要做的就是将进程和指定的Application绑定起来. 这个是通过上节的ActivityThread对象中调用bindApplication()方法完成的. 该方法发送一个BIND_APPLICATION的消息到消息队列中, 最终通过handleBindApplication()方法处理该消息. 然后调用makeApplication()方法来加载App的classes到内存中.

6.3 启动Activity

 

经过前两个步骤之后, 系统已经拥有了该application的进程. 后面的调用顺序就是普通的从一个已经存在的进程中启动一个新进程的activity了.

实际调用方法是realStartActivity(), 它会调用application线程对象中的sheduleLaunchActivity()发送一个LAUNCH_ACTIVITY消息到消息队列中, 通过 handleLaunchActivity()来处理该消息.

假设点击的是一个视频浏览的App, 其流程如下: