Android应用程序执行流程

Android应用程序运行时会先读取AndroidManifest.xml清单文件,根据清单文件中的配置信息设置应用程序的基本信息,通过过滤条件查找到入口的Activity,并查找到对应的类名,然后创建该类的实例。接着会调用该类的onCreate方法设置Activity显示界面。

APP启动流程

Android应用的启动流程

你所看到的手机桌面Launcher也是继承自Activity的,当安装完以一个APP之后会在手机桌面Launcherr上生成 以一个对应的APP图标。首次点击图标时Launcher会启动图标对应APP的首页Activity,一般而言启动的都是项目工程中的MainActivity,其实这个过程是一个Activity的启动的过程,与在APP内部启动一个Activity不同的是:点击桌面Launcher首次启动APP时会先去建立APP对应的进程,然后再执行ActivityThread的main()方法去创建对应的Application,最后再启动首页Activity。

当用户点击APP图标时会启动Launcher与应用程序,Launcher继承自Activity并实现了点击长按监听。此时Luncher会通过Intent发送startActivity请求,通过binder机制调用ActivityManagerService通讯,经过一些列操作后调用startProcessLocked方法,并通过Socket通道传递参数给Zygote进程。此时Zygote进程会调用ZygoteInit.main()方法产生一个新的进程并返回PID,最后调用ActivityThread.main方法来实例化ActivityThread对象。此时Activity进程真正开始...

Activity启动流程

当点击桌面Launcher首次进入APP时,会走Activity的startActivity()的过程,在启动一个新的Activity之前会先执行当前Activity的onPause()方法,会将当前Activity给Pause掉。如果是点击桌面Launcher首次进入APP的话,这个当前的Activity指的是桌面Launcher的Activity。当前Activity执行onPause()之后,如果当前应用的进程已经创建,这种情况下指得是在APP内部的Activity的跳转,那么就会去通过ActivityManagerService中持有的ActivityThread中的ApplicationThread这个Binder对象来立即创建一个新的Activity,并执行该Activity声明周期的方法。如果当前应用的进程没有创建也就是首次进入APP,那么这个时候会先通过Process.start()方法来创建一个进程,在创建的过程中会去调用ActivityThread的main()方法,在这个main()方法中会创建一些必备的东西比如主线程的Looper等,并且在main()方法中会执行Application的创建过程,通过ActivityManagerService来创建一个Application,在创建完成后会启动一个Activity,这个Activity值得是默认启动的首页Activity,也就是通常所说的MainActivity。

清单文件AndroidManifest.xml

Application的创建过程

整个Android应用启动的入口是ActivityThread的main()方法,Application的创建也是在这个main()方法中。

Application类

  • Applicaton是维护全局状态的基类,Android系统会在启动APP进程时创建一个Application对象,Application中的对象变量是属于整个系统的。
  • 在启动APP时会创建Application对象,所以Application对象诞生于其他任何组件对象之前,并且一直存活直到APP进程结束。
  • 默认情况下Android系统会为每个APP分配 一个进程,进程名称是项目的包名,当进程启动时Android系统会创建Application对象并调用对象的onCreate方法。
  • Application在项目运行过程中不会改变,而Activity在切换过程中会有不断地创建和销毁,Service服务切换也会创建和销毁,但是Application则不会改变。
  • Application对象由Android系统管理,其回调函数都运行于主线程(UI线程),回调函数包括onCreate创建、onConfigurationChanged系统配置变更(包括屏幕方向变化、系统语言变化等)、onLowMemory释放内存
  • Application对象是全局可访问的,而且全程陪同APP进程,适合共享状态,初始化应应用所需的服务。
  • 静态单例也可以是西安全局状态的共享

Application和Activity、Service一样都是Android框架的系统组件,当APP启动时系统会创建一个Application对象用来存储系统的信息。Android系统会自动为每个程序运行时创建一个Application类的对象且只创建一个,所以Application可以说是单例(singleton)模式的一个类。

通常无需手动指定Application,系统会自动创建。如果需要手工创建只需要创建一个继承自Application的类并在AndroidManifest.xml清单文件中的<appilcation>标签中进行注册,也就是给<application>标签增加android:name属性。

<application android:name=".MainApplication"></application>

继承Application的类主要需要重写父类的onCreate()方法,因为android.app.Application包中的onCreate()方法才是真正的Android程序的入口点。在onCreate()方法主要用于创建时初始化变量的值,然后在整个应用中的各个文件中就可以对该变量进行操作。

$ vim MainApplication.java
package com.weihuagu.receiptnotice;
import android.app.Application;
import android.content.Intent;

import com.tao.admin.loglib.TLogApplication;
import com.tao.admin.loglib.IConfig;
public class MainApplication extends Application {
        @Override
        public void onCreate() {
                super.onCreate();
                startNotificationService();
                initLogConfig();
        }
        private void initLogConfig(){
                TLogApplication.initialize(this);
                IConfig.getInstance().isShowLog(false)//是否在logcat中打印log,默认不打印
                .isWriteLog(true)//是否在文件中记录,默认不记录
                .tag("GoFileService");//logcat 日志过滤tag
        }
        private void startNotificationService(){
                startService(new Intent(this, NotificationCollectorMonitorService.class));
        }
}

android.app.Application类包含了四个公开的方法

  • void onConfigurationChanged(Configuration newConfig)
  • void onCreate()
  • void onLowMemory()
  • void onTerminate()

Application的生命周期

  • onCreate 在创建应用程序时创建
  • onTerminate 当终止应用程序对象时调用,不保证一定被调。
    当程序是被内核终止以便为其他应用程序释放资源,那么将不会提醒,并且不会调用Application对象的onTerminate()方法而直接终止进程。
  • onLowMemory 当后台程序已经终止资源还匮乏时会调用此方法,好的应用程序一般会在此方法中释放一些不必要的资源来应付当后台程序已经终止,前台应用程序内存仍不足够时的情况。
  • onConfigurationChanged 配置改变时触发

Application被杀死的情况

为了决定在内存较低时杀掉哪个进程,Android会根据运行在这些进程内的组件以及状态将进程划分成一个重要程度层次,其重要程度按一下规则排序。

  1. 前端进程可以是一个持有运行在屏幕最前端并与用户交互的Activity的进程(onResume()方法被调用时),也可以是持有一个正在运行的IntentReceiver(正在执行自己的onReceiveIntent()方法)的进程。在系统中,只会有少数这样的进程,除非内存已经低到不够这些进程运行,否则系统不会主动杀掉这些进程。此时设备通常已经达到需要内存整理的状态,所以杀掉这些进程是为了不让用户界面停止响应。
  2. 可视进程是持有一个被用户可见,但没有显示在最前端(onPause方法被调用时)的Activity进程。比如这种进程通常出现在一个前端Activity以一个对话框出现并保持前一个Activity可见时,这种进程被系统认为是极为重要的,并且通常不会被杀掉,除非为了保持所有前端进程正常运行不得不杀掉这些可见进程。
  3. 服务进程是持有有一个Service的进程,该Service是由startService()方法启动的,尽管这些进程用户不能直接看到,但通常它们所作的工作是用户十分关注的。比如在后台播放MP3或在后台下载上传文件。所以,除非为了保持所有的前端进程和可视进程正常运行外,,系统是不会杀掉服务进程的。
    4.后台进程是持有一个不再被用户可见的Activity(onStop方法被调用时)的进程,这些进程不会直接影响用户体验,加入这些进程已经完成了自己的生命周期,系统会为前三种进程释放内存时随时杀掉这些后台进程。通常会有很多的后台进程在运行,所以这些进程被存放在一个LRU列表中,以保证在低内存的时候,最后一个被用户看到的进程会被最后杀掉。
    5.空进程是没有持有任何活动应用组件的进程,保留这种进程的唯一理由是为了提供一种缓存机制,缩短应用下次运行时的启动时间。就其本身而言,系统杀掉这些进程的鳄目的是为了在这些空进程和底层核心缓存之间平衡整个系统的资源。

当启动Application时系统会创建一个进程ID(PID),所有的Activity都会在此进程上运行。在Application创建的时候会初始化全局变量,同一个应用的所有Activity都可以获取到这些全局变量的值。换句话说,在某个Activity中改变了全局变量的值会影响到同一个应用中其他Activity中的值。

Application对象的生命周期是整个程序中最长的,基本上等同于应用的生命周期。因为是全局单例的,所以在 不同的Activity、Service中获取得到的对象都是同一个对象。因此可以通过Application来进行一些操作,比如数据传递、数据共享、数据缓存等。

Application传递数据

假如有一个ActivityA跳转到ActivityB并需要推荐一些数据,通常的做法是使用Intent.putExtra()方法让Intent携带,或者使用一个Bundle将信息让Intent推荐Bundle对象实现传递。但这样做的问题在于Intent和Bundle所能携带的数据类型都是基本数据类型,如果想要实现复杂数据类型传递就比较麻烦,通常需要实现Serializable或Parcellable接口,这其实是Android的一种IPC数据传输的方法。如果两个Activitty在同一个进程中为什么还需要这么麻烦呢?只需将要传递的数据引用传递过去即可。实现的基本思路是在Application中创建一个HashMap,以字符串为索引,Object为值得方式。在ActivityA中将需要传递的对象放入HashMap,然后通过Intent或其他途径将索引字符串传递给ActivityB,AactivityB会根据这个字符串在HashMap中获取出目标对象。只要再向下转型就实现了对象的传递。

Application数据缓存

一般习惯会再Application中建立两个HashMap,一个用于数据传递,一个用于缓存数据。比如有一个Activity需要从网站中获取数据,获取完毕后可以将数据缓存到Application中,当页面设置到其他Activity再回来时,可以直接使用给缓存好的数据。但如果需要缓存一些大量数据,最好是缓存一些软引用(SoftReference),并将这些数据缓存到本地ROM或SD卡上。如果再Application中的缓存不存在,可以从本地缓存中查找,如果本地缓存的数据也不存在则再从网络中获取。

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

推荐阅读更多精彩内容