Android UI-对Activity工作流程的理解(一)

概述

在android studio创建一个新项目的时候,或者初学者在刚踏入android开发的时候,都会在首先创建一个MainActivity。根据一般的理解,Activity的就相当于一个界面的入口,所有和界面相关的代码都可以在activity中编写。但是随着经验的增加和项目的深入,不禁要问activity的原理是什么?为什么我们在onCreate()中设置contentView,然后显式或者隐式启动这个activity,就能够在界面上显示,就能够响应用户的点击事件了呢?

其实Activity并不直接是一个能够显示页面的类。在启动时,Activity先通过Binder机制向ActivityServiceManager注册,然后Service通过调用ApplicationThread中的方法向主线程的Handler发送消息,Handler调用ActivityThread中的方法处理activity的创建过程。创建Activity时新建一个DecorView对象,而DecorView正是这个activity界面所有view的根对象。随后,将用户定义的ContentView添加到DecorView中。到这里Activity应该已经创建完成了,但差一个很重要的过程,还没有显示出来!创建以后会继续调用Resume方法,这里会将DecorView注册到WindowManagerService中,然后界面就能接收外界的输入消息了并且显示了。到这里,Activity的视图才最终被用户所看到。页面显示后,系统会将点击事件传递给Activity,用户就可以与Activity视图进行交互了。

那么如何开始我们的启动之旅呢。首先,我们先了解下android系统的架构,相信很多人在刚开始学的时候就已经看过这个框架。我们先看一下系统的framework层和我们应用之间的关系,先有一个整体的概念。其次,应用启动的时候,都会启动一个dalvik虚拟机,然后运行应用的主线程,然后再去加载我们的activity,我们就一步一步去跟踪Activity'的启动流程。所以这一篇先介绍framework层,再介绍如何看源码。具体的activity实现流程等到以后的博客中再去分析。

应用与framework层的关系

android框架

相信大家都对这张框架图不陌生,从整体框架来看,主要分为Linux内核层,库和运行时层,framework层和应用层。以本人的能力,当然无法讲解整个体系,只是说一下framework层和应用的联系的一点理解。


Paste_Image.png

android framework层

我们观察framework层的各个子模块,会发现一个共同点,他们都是以manager、service、provider结尾的。这让我们想到了framework层的作用大概是提供服务或者管理用的层。因为系统会通过各种manager管理我们的应用,也会向我们提供各种服务,所以我们猜测,那么我们在创建应用或者创建activity时,必然会和各种framework层的模块打交道。

系统service的启动

在Android启动过程中,系统会启动各种framework层的服务。所以来看下SystemServer这个类。从名字可以看出它提供了系统运行时所需要各种java编写的“系统服务”。

public static void main(String[] args) {
  new SystemServer().run();
 }

 public SystemServer() {
  // Check for factory test mode.
   mFactoryTestMode = FactoryTest.getMode();
 }

 private void run() {
  ...
  // Start services.
  try {
    //启动引导服务
    startBootstrapServices();
    //启动核心服务
    startCoreServices();
    //启动另外一些服务
    startOtherServices();
  } catch (Throwable ex) {
    throw ex;
 }
  ...
 // Loop forever.
  Looper.loop(); 
  throw new RuntimeException("Main thread loop unexpectedly exited");
}

在启动引导和核心服务的方法中会启动如下一些service和manager

private PowerManagerService mPowerManagerService;
private ActivityManagerService mActivityManagerService;
private DisplayManagerService mDisplayManagerService;
private PackageManagerService mPackageManagerService;
private PackageManager mPackageManager;

在启动另外的服务时会启动如下一些service(没有列全)

NetworkManagementService networkManagement = null;
ConnectivityService connectivity = null;
WindowManagerService wm = null;
InputManagerService inputManager = null;
TelephonyRegistry telephonyRegistry = null;
AudioService audioService = null;
CameraService cameraService = null;

系统service与应用如何交互

看到这些名字,我们都会感觉很熟悉,因为在写应用的时候,经常或通过java context.getSystemService(Context.ACTIVITY_SERVICE);这样的方法去拿到系统的服务。其实,我们并不是拿到了正真的系统服务,因为系统服务并不是在我们应用所在的进程中运行,所以我们拿到的是系统服务的入口对象。如下代码所示,最终我们会在SystemServiceRegistry中获得一个ActivityManger对象。Activity对象中通过ActivityManagerNative.getDefault()这个Binder对象来与系统服务进行通信。(关于Binder,后续会给一个大致的介绍,这边主要讲framework与应用的关系,所以不再继续深入下去)。

SystemServiceRegistry{
  ...
  static{
    ...
    registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,
        new CachedServiceFetcher<ActivityManager>() {
    @Override
    public ActivityManager createService(ContextImpl ctx) {
        return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
    }});
    ...
  }
}

那么我们讲了这么多,有什么用呢。其实activity的启动与framework有莫大的联系,如果没有系统服务,那么我们的进程就无法显示,activity就无法创建,view就无法绘制,滑动点击事件也无法传递给应用,说到底,我们的应用构建在系统服务至上。在后续的介绍中,会着重去跟踪几个系统服务的类,所以说先在开始时从宏观上介绍一下我们到底和谁在通信,为什么要通信。

关联相应的源码

目前android studio是主流的android 开发软件,一般在android应用创建以后,会关联默认的android部分源码。如果希望获得其他版本的源码,可以通过SDK Manager进行下载。我使用的是android-23的源码。


Paste_Image.png

如何调试Studio源码

点击菜单栏的“Run”->“Attach debugger to Android process”,选择需要调试的进程。然后再源码上加断点,debug就可以断在相应的位置。如果开始attach到app的进程,则看不到系统应用的进程的断点。如果需要调试ActivityMangerService这样的系统服务类的话,那么需要attach到system_process,然后对自己的应用进行断点调试。

Paste_Image.png

如上图所示,我们算是成功的进行了断点。

总结

这里我们介绍了framework层和activity的关系,简单说了下如何调试源码。接下去,会介绍线程及线程入口,及android非常重要的looper机制。这也是理解activity运行机制的非常重要的一部分。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,368评论 25 707
  • 1.什么是Activity?问的不太多,说点有深度的 四大组件之一,一般的,一个用户交互界面对应一个activit...
    JoonyLee阅读 5,724评论 2 51
  • 作者: 美国 steve krug 一 指导原则: 1 可用性第一原则: 不需要思考 :(设计的内容或者按钮 不应...
    五六环之间阅读 788评论 0 4
  • 闪烁诉说着孤寂 想要的自由在哪里 千百次的盘旋环绕 只看到银河的光亮绚丽夺目 浩瀚宇宙的边际 是否充斥黑暗 还是演...
    文活阅读 195评论 1 1
  • 锦瑟无罪 在有海的城市想念自己 青春之尾 长长长长的旅途与永远 当夜深人静的时候,我才能写下自...
    死在水里的鱼阅读 335评论 0 2