iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Android中ActivityThread和APP初始化的示例分析
  • 850
分享到

Android中ActivityThread和APP初始化的示例分析

2023-06-15 10:06:12 850人浏览 薄情痞子
摘要

这篇文章将为大家详细讲解有关Android中ActivityThread和APP初始化的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。ActiviryThreadActivityThread的初始

这篇文章将为大家详细讲解有关Android中ActivityThread和APP初始化的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

ActiviryThread

ActivityThread的初始化

ActivityThread即Android的主线程,也就是UI线程,ActivityThread的main方法是一个APP的真正入口,MainLooper在它的main方法中被创建。

//ActivityThread的main方法public static void main(String[] args) {    ...    Looper.prepareMainLooper();    ActivityThread thread = new ActivityThread();    //在attach方法中会完成Application对象的初始化,然后调用Application的onCreate()方法    thread.attach(false);    if (sMainThreadHandler == null) {        sMainThreadHandler = thread.getHandler();    }    ...    Looper.loop();    throw new RuntimeException("Main thread loop unexpectedly exited");}

接下来从主线程Looper的初始化和ApplicationThread及Activity的创建启动两方面,通过源码了解学习下大致的流程。

主线程Looper的初始化

Looper.prepareMainLooper();相关的代码如下

//主线程Looper的初始化public static void prepareMainLooper() {    prepare(false);    synchronized (Looper.class) {        if (sMainLooper != null) {            throw new IllegalStateException("The main Looper has already been prepared.");        }        sMainLooper = myLooper();    }}//普通线程Looper的初始化public static void prepare() {    prepare(true);}private static void prepare(boolean quitAllowed) {    if (sThreadLocal.get() != null) {        throw new RuntimeException("Only one Looper may be created per thread");    }    sThreadLocal.set(new Looper(quitAllowed));}

看过Handler源码就知道,主线程Looper的初始化和普通线程Looper的初始化很相似,但还是有以下几个区别

普通线程的Prepare()默认quitAllowed参数为true,表示允许退出,而主线程也就是ActivityThread的Looper参数为false,不允许退出。这里的quitAllowed参数,最终会传递给MessageQueue,当调用MessageQueue的quit方法时,会判断这个参数,如果是主线程,也就是quitAllowed参数为false时,会抛出异常。

//Looper的退时会判断quitAllowedvoid quit(boolean safe) {    if (!MQuitAllowed) {        throw new IllegalStateException("Main thread not allowed to quit.");    }    synchronized (this) {        ...    }}

我们注意到主线程Looper初始化之后,赋值给了成员变量sMainLooper,这个成员的作用就是向其他线程提供主线程的Looper对象。这下我们就应该知道为什么Looper.getMainLooper()方法能获取主线程的Looper对象了

public static Looper getMainLooper() {    synchronized (Looper.class) {        return sMainLooper;    }}

主线程Handler的初始化

在ActivityThread的main方法中我们注意到一行代码:

ActivityThread thread = new ActivityThread();thread.attach(false);if (sMainThreadHandler == null) {    sMainThreadHandler = thread.getHandler();}

见名知意,这是获取主线程的Handler,那么主线程的Handler是在什么时候初始化的呢?

//与之相关的代码如下://ActivityThread的成员变量final H mH = new H();final Handler getHandler() {    return mH;}

从以上代码中可以看到,主线程的Handler作为ActivityThread的成员变量,是在ActivityThread的main方法被执行,ActivityThread被创建时而初始化,而接下来要说的ApplicationThread中的方法执行以及Activity的创建都依赖于主线程Handler。至此我们也就明白了,主线程(ActivityThread)的初始化是在它的main方法中,主线程的Handler以及MainLooper的初始化时机都是在ActivityThread创建的时候。

ApplicationThread及Activity的创建和启动

以上的代码和流程,就是对 MainLooper 和 ActivityThread 的初始化,我们接下来看一下 ActivityThread 的初始化及其对应的 attach 方法,在thread.attach方法中,ActivityManagerService通过attachApplication方法,将ApplicationThread对象绑定到ActivityManagerService,ApplicationThread是ActivityThread的私有内部类,实现了IBinder接口,用于ActivityThread和ActivityManagerService的所在进程间通信。

//ActivityThread的attach方法:private void attach(boolean system) {    ...    if (!system) {        final IActivityManager mgr = ActivityManager.getService();        try {            mgr.attachApplication(mAppThread);        } catch (RemoteException ex) {            throw ex.rethrowFromSystemServer();        }else{            ...        }    }}//ActivityManagerService中的方法:public final void attachApplication(IApplicationThread thread) {    synchronized (this) {        int callingPid = Binder.getCallingPid();        final long origId = Binder.clearCallingIdentity();        attachApplicationLocked(thread, callingPid);        Binder.restoreCallingIdentity(origId);    }}

这里的个人理解是:在每个ActivityThread(APP)被创建的时候,都需要向ActivityManagerService绑定(或者说是向远程服务AMS注册自己),用于AMS管理ActivityThread中的所有四大组件的生命周期。

上述AMS的代码中attachApplicationLocked方法比较复杂,主要功能有两个,详见注释,这里忽略了很多代码细节,具体的流程可以看源码

//AMS中的方法,主要功能有以下两步private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {    ...    //主要用于创建Application,用调用onCreate方法    thread.bindApplication(...);    ...    //主要用于创建Activity    if (mStackSupervisor.attachApplicationLocked(app)) {        ...    }}

thread.bindApplication:主要用于创建Application,这里的thread对象是ApplicationThread在AMS中的代理对象,所以这里的bindApplication方法最终会调用ApplicationThread.bindApplication()方法,该方法会向ActivityThread的消息对应发送BIND_APPLICATION的消息,消息的处理最终会调用Application.onCreate()方法,这也说明Application.onCreate()方法的执行时机比任何Activity.onCreate()方法都早。

//ActivityThread中的bindApplication方法public final void bindApplication(...) {    ...    // 该消息的处理,会调用handleBindApplication方法    sendMessage(H.BIND_APPLICATION, data);}//ActivityThread中的handleBindApplication方法private void handleBindApplication(AppBindData data) {    ...    try {        Application app = data.info.makeApplication(data.restrictedBackupMode, null);        mInitialApplication = app;        ...        try {            mInstrumentation.callApplicationOnCreate(app);        } catch (Exception e) {        }    } finally {    }}    //LoadedApk中的方法,用于创建Applicationpublic Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {    //如果存在Application的实例,则直接返回,这也说明Application是个单例    if (mApplication != null) {        return mApplication;    }    Application app = null;    //...这里通过反射初始化Application    if (instrumentation != null) {        try {            //调用Application的onCreate方法            instrumentation.callApplicationOnCreate(app);        } catch (Exception e) {        }    }    return app;}

mStackSupervisor.attachApplicationLocked(app):用于创建Activity,mStackSupervisor是AMS的成员变量,为Activity堆栈管理辅助类实例,该方法最终会调用ApplicationThread类的scheduleLaunchActivity方法,该方法也是类似于第一步,向ActivityThread的消息队列发送创建Activity的消息,最终在ActivityThread中完成创建Activity的操作。

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {    ...    if (realStartActivityLocked(hr, app, true, true)) {        ...    }              ...}final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,    boolean andResume, boolean checkConfig) throws RemoteException {    ...    try {        //调用ApplicationThread的scheduleLaunchActivity用于启动一个Activity        app.thread.scheduleLaunchActivity(...);    } catch (RemoteException e) {    }}

ApplicationThread的scheduleLaunchActivity方法会向ActivityThread发送LAUNCH_ACTIVITY信息,用于启动一个Activity,该消息的处理会调用ActivityThread的handleLaunchActivity方法,最终启动一个Activity

以上就是从ActivityThread的main方法执行到Activity的创建之间的流程,至于ActivityThread的main方法执行时机,以及执行前的流程和Activity的具体创建过程,可以接着看APP的启动过程

APP的启动

系统的启动过程

在学习APP的启动之前先简单了解下系统的启动,有助于我们更好的学习APP的启动。系统的启动过程很复杂,这里简单化,只关心大致流程和涉及到的一些名词以及相关类的作用

APP的启动可以简单总结为一下几个流程:

加载BootLoader --> 初始化内核 --> 启动init进程 --> init进程fork出ZyGote进程 --> Zygote进程fork出SystemServer进程

Android中ActivityThread和APP初始化的示例分析

  • 系统中的所有经常进程都是由Zygote进程fork出来的

  • SystemServer进程是系统进程,很多系统服务,例如ActivityManagerService、PackageManagerService、WindowManagerService…都是存在该进程被创建后启动

  • ActivityManagerServices(AMS):是一个服务端对象,负责所有的Activity的生命周期,AMS通过Binder与Activity通信,而AMS与Zygote之间是通过Socket通信

  • ActivityThread:本篇的主角,UI线程/主线程,它的main()方法是APP的真正入口

  • ApplicationThread:一个实现了IBinder接口的ActivityThread内部类,用于ActivityThread和AMS的所在进程间通信

  • Instrumentation:可以理解为ActivityThread的一个工具类,在ActivityThread中初始化,一个进程只存在一个Instrumentation对象,在每个Activity初始化时,会通过Activity的Attach方法,将该引用传递给Activity。Activity所有生命周期的方法都有该类来执行

APP的启动过程

APP的启动,我们使用一张图来说明这个启动过程,顺便也总结下上面所说的ActivityThread的main方法执行到Activity的创建之间的流程。

Android中ActivityThread和APP初始化的示例分析

点击桌面APP图标时,Launcher的startActivity()方法,通过Binder通信,调用system_server进程中AMS服务的startActivity方法,发起启动请求

system_server进程接收到请求后,向Zygote进程发送创建进程的请求

Zygote进程fork出App进程,并执行ActivityThread的main方法,创建ActivityThread线程,初始化MainLooper,主线程Handler,同时初始化ApplicationThread用于和AMS通信交互

App进程,通过Binder向sytem_server进程发起attachApplication请求,这里实际上就是APP进程通过Binder调用sytem_server进程中AMS的attachApplication方法,上面我们已经分析过,AMS的attachApplication方法的作用是将ApplicationThread对象与AMS绑定

system_server进程在收到attachApplication的请求,进行一些准备工作后,再通过binder IPC向App进程发送handleBindApplication请求(初始化Application并调用onCreate方法)和scheduleLaunchActivity请求(创建启动Activity)

App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送BIND_APPLICATION和LAUNCH_ACTIVITY消息,这里注意的是AMS和主线程并不直接通信,而是AMS和主线程的内部类ApplicationThread通过Binder通信,ApplicationThread再和主线程通过Handler消息交互。 ( 这里猜测这样的设计意图可能是为了统一管理主线程与AMS的通信,并且不向AMS暴露主线程中的其他公开方法)

主线程在收到Message后,创建Application并调用onCreate方法,再通过反射机制创建目标Activity,并回调Activity.onCreate()等方法

到此,App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染后显示APP主界面

APP启动过程的部分代码思考

在上面学习APP的启动过程中,看源码的同时注意到一个代码,就是主线程Handler在接收到LAUNCH_ACTIVITY创建Activity的消息后,创建Activity的部分代码如下:

//主线程Handler接收到创建Activity的消息LAUNCH_ACTIVITY后,最终会调用perfORMLaunchActivity方法//performLaunchActivity方法会通过反射去创建一个Activity,然后会调用Activity的各个生命周期方法private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {    ...    ContextImpl appContext = createBaseContextForActivity(r);    Activity activity = null;    try {        //这里是反射创建Activity        java.lang.ClassLoader cl = appContext.getClassLoader();        activity = mInstrumentation.newActivity(                cl, component.getClassName(), r.intent);        StrictMode.incrementExpectedActivityCount(activity.getClass());        r.intent.setExtrasClassLoader(cl);        r.intent.prepareToEnterProcess();        if (r.state != null) {            r.state.setClassLoader(cl);        }    }    try {        //这里注意,又调用了一次Application的创建方法,但是前面分析过,Application是个单例,所以这里的实际上是获取Application实例,但是这里为什么会再次调用创建Application的方法呢?                Application app = r.packageInfo.makeApplication(false, mInstrumentation);        ...    }     ...    return activity;}

在上面的代码中,简单注释了一下在Activity的创建方法中,会再次调用Application的创建方法(第一次调用是在接收到BIND_APPLICATION消息的时候),个人觉得这里再次调用Application的创建方法,除了获取已经存在的Application实例这种情况,另外一种情况还有可能是要创建的这个Activity属于另外一个进程,当去启动这个新进程中的Activity时,会先去创建新进程和Application实例,因为我们知道一个常识:

APP中有几个进程,Application会被创建几次

新进程中所有变量和单例会失效,因为新进程有一块新的内存区域

那么这两点的关系就是,因为新进程中Application实例会为空,所以会再次去创建Application实例,这也就是第一点中我们所说的常识:APP中有几个进程,Application会被创建几次

//创建Application的方法public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {    //如果存在Application的实例,则直接返回,这也说明Application是个单例    if (mApplication != null) {        return mApplication;    }    Application app = null;    //...创建Application    return app;}

那么依次类推,Service作为四大组件之一,类似于Activity的创建和启动,创建Service的方法中会不会也调用了创建Application的方法(makeApplication方法),答案是肯定的!和Activity的创建类似,当我们调用startService的时候,也是通过Binder向AMS发送创建Service的请求,AMS准备后再向APP进程发送scheduleCreateService的请求,然后主线程handle收到CREATE_SERVICE的消息,调用handleCreateService创建Service的方法。在创建Service的方法handleCreateService中也调用了创建Application的方法,具体代码看源码吧。所以我们也彻底明白了为什么APP中有几个进程,Application会被创建几次,以及Application为什么是个单例。

关于“Android中ActivityThread和APP初始化的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

--结束END--

本文标题: Android中ActivityThread和APP初始化的示例分析

本文链接: https://www.lsjlt.com/news/279923.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android中ActivityThread和APP初始化的示例分析
    这篇文章将为大家详细讲解有关Android中ActivityThread和APP初始化的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。ActiviryThreadActivityThread的初始...
    99+
    2023-06-15
  • Vue实例初始化的示例分析
    这篇文章将为大家详细讲解有关Vue实例初始化的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。以下正式开始:Vue官网的生命周期图示表重点说一下 new Vue()...
    99+
    2024-04-02
  • vue-router初始化的示例分析
    这篇文章主要为大家展示了“vue-router初始化的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“vue-router初始化的示例分析”这篇文章吧。v...
    99+
    2024-04-02
  • Spring框架初始化的示例分析
    这篇文章将为大家详细讲解有关Spring框架初始化的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、Spring能做什么?Spring的主要目的是使J2EE易用和促进好编程习惯。倒置控制容器 S...
    99+
    2023-05-30
    spring
  • CSS5初始化模板的示例分析
    这篇文章给大家分享的是有关CSS5初始化模板的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。 CSS5初始化模板席卷了GBK编码内容和UTF-8编码内容的两个编码模板。...
    99+
    2024-04-02
  • 初始Spring的示例分析
    小编给大家分享一下初始Spring的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!为什么要使用SpringWhy SpringSpring makes p...
    99+
    2023-06-20
  • webstorm+vue初始化项目的示例分析
    小编给大家分享一下webstorm+vue初始化项目的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!vue新项目准备:1、安装nodejs,官网下载傻瓜安装node -v 验证2、...
    99+
    2024-04-02
  • JVM中加载、链接、初始化的示例分析
    这篇文章主要为大家展示了“JVM中加载、链接、初始化的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“JVM中加载、链接、初始化的示例分析”这篇文章吧。基本概念:类加载的过程大致分为三个阶...
    99+
    2023-05-31
    jvm
  • Java类和对象初始化过程的示例分析
    这篇文章主要介绍了Java类和对象初始化过程的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。  问题引入  近日我在调试一个枚举类型的解析器程序,该解析器是将数据库内...
    99+
    2023-06-03
  • Angular.js基础学习之初始化的示例分析
    这篇文章将为大家详细讲解有关Angular.js基础学习之初始化的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、绑定初始化,自动加载通过绑定来进行angula...
    99+
    2024-04-02
  • kubernetes中Pod初始化容器之Init Container的示例分析
    这篇文章主要介绍了kubernetes中Pod初始化容器之Init Container的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一:前言在很多应用场景中,应用在...
    99+
    2023-06-04
  • C#中变量初始化实例分析
    本文小编为大家详细介绍“C#中变量初始化实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“C#中变量初始化实例分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。请看下面的实例,使用了各种类型的变量:name...
    99+
    2023-06-17
  • 详解Android中的ActivityThread和APP启动过程
    目录ActiviryThreadActivityThread的初始化主线程Looper的初始化主线程Handler的初始化ApplicationThread及Activity的创建和...
    99+
    2024-04-02
  • C++的定义,声明和初始化实例分析
    这篇文章主要介绍了C++的定义,声明和初始化实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++的定义,声明和初始化实例分析文章都会有所收获,下面我们一起来看看吧。定义变量的定义用于为变量分配存储空间,...
    99+
    2023-06-29
  • CentOS系统常规初始化操作的示例分析
    小编给大家分享一下CentOS系统常规初始化操作的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!环境准备:1)设置本地国际化语言为en_US.UTF-8[...
    99+
    2023-06-10
  • SpringMVC初始化流程实例分析
    本文小编为大家详细介绍“SpringMVC初始化流程实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“SpringMVC初始化流程实例分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1.HttpServl...
    99+
    2023-07-02
  • Swift中类与结构的初始化示例解析
    目录一,结构的初始化二,结构的初始化三,结构中初始化错误示例四,结构中init可以通过self关键字调用其他的init五,类初始化错误示例六,类的(Designated init)初...
    99+
    2024-04-02
  • Android中的ActivityThread和APP启动过程是什么
    ActivityThread是Android中负责管理所有Activity的线程,它负责处理Activity的生命周期、事件分发、消...
    99+
    2024-03-08
    Android
  • Java中实例初始化和静态初始化的过程详解
    目录一、实例初始化1.1 实例初始化过程1.2 实例初始化的顺序1.3 实例初始化的注意事项二、静态初始化2.1 静态初始化过程2.2 静态初始化的顺序2.3 静态初始化的注意事项三...
    99+
    2023-05-18
    Java实例初始化和静态初始化 Java实例初始化 Java静态初始化 Java初始化
  • java数组初始化的示例
    小编给大家分享一下java数组初始化的示例,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!Java可以用来干什么Java主要应用于:1. web开发;2. Android开发;3. 客户端开发;4. 网页开发;5. 企业级应...
    99+
    2023-06-14
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作